diff --git a/src/s3fs.cpp b/src/s3fs.cpp index d6c46e5..d12f980 100644 --- a/src/s3fs.cpp +++ b/src/s3fs.cpp @@ -4529,6 +4529,14 @@ int main(int argc, char* argv[]) exit(EXIT_FAILURE); } + // mutex for basename/dirname + if(!init_basename_lock()){ + S3FS_PRN_EXIT("could not initialize mutex for basename/dirname."); + s3fs_destroy_global_ssl(); + destroy_parser_xml_lock(); + exit(EXIT_FAILURE); + } + // init curl (without mime types) // // [NOTE] @@ -4549,6 +4557,7 @@ int main(int argc, char* argv[]) S3FS_PRN_EXIT("Could not initiate curl library."); s3fs_destroy_global_ssl(); destroy_parser_xml_lock(); + destroy_basename_lock(); exit(EXIT_FAILURE); } @@ -4563,6 +4572,7 @@ int main(int argc, char* argv[]) S3fsCurl::DestroyS3fsCurl(); s3fs_destroy_global_ssl(); destroy_parser_xml_lock(); + destroy_basename_lock(); exit(EXIT_FAILURE); } @@ -4579,6 +4589,7 @@ int main(int argc, char* argv[]) S3fsCurl::DestroyS3fsCurl(); s3fs_destroy_global_ssl(); destroy_parser_xml_lock(); + destroy_basename_lock(); exit(EXIT_FAILURE); } if(!S3fsCurl::FinalCheckSse()){ @@ -4586,6 +4597,7 @@ int main(int argc, char* argv[]) S3fsCurl::DestroyS3fsCurl(); s3fs_destroy_global_ssl(); destroy_parser_xml_lock(); + destroy_basename_lock(); exit(EXIT_FAILURE); } @@ -4605,6 +4617,7 @@ int main(int argc, char* argv[]) S3fsCurl::DestroyS3fsCurl(); s3fs_destroy_global_ssl(); destroy_parser_xml_lock(); + destroy_basename_lock(); exit(EXIT_FAILURE); } @@ -4619,6 +4632,7 @@ int main(int argc, char* argv[]) S3fsCurl::DestroyS3fsCurl(); s3fs_destroy_global_ssl(); destroy_parser_xml_lock(); + destroy_basename_lock(); exit(EXIT_FAILURE); } } @@ -4629,6 +4643,7 @@ int main(int argc, char* argv[]) S3fsCurl::DestroyS3fsCurl(); s3fs_destroy_global_ssl(); destroy_parser_xml_lock(); + destroy_basename_lock(); exit(EXIT_FAILURE); } @@ -4638,6 +4653,7 @@ int main(int argc, char* argv[]) S3fsCurl::DestroyS3fsCurl(); s3fs_destroy_global_ssl(); destroy_parser_xml_lock(); + destroy_basename_lock(); exit(EXIT_FAILURE); } @@ -4681,6 +4697,7 @@ int main(int argc, char* argv[]) S3fsCurl::DestroyS3fsCurl(); s3fs_destroy_global_ssl(); destroy_parser_xml_lock(); + destroy_basename_lock(); exit(exitcode); } @@ -4695,6 +4712,7 @@ int main(int argc, char* argv[]) S3fsCurl::DestroyS3fsCurl(); s3fs_destroy_global_ssl(); destroy_parser_xml_lock(); + destroy_basename_lock(); exit(EXIT_FAILURE); } @@ -4704,6 +4722,7 @@ int main(int argc, char* argv[]) S3fsCurl::DestroyS3fsCurl(); s3fs_destroy_global_ssl(); destroy_parser_xml_lock(); + destroy_basename_lock(); exit(EXIT_FAILURE); } @@ -4764,6 +4783,7 @@ int main(int argc, char* argv[]) } s3fs_destroy_global_ssl(); destroy_parser_xml_lock(); + destroy_basename_lock(); // cleanup xml2 xmlCleanupParser(); diff --git a/src/s3fs_util.cpp b/src/s3fs_util.cpp index 2a9d27e..23a2c7f 100644 --- a/src/s3fs_util.cpp +++ b/src/s3fs_util.cpp @@ -37,6 +37,7 @@ #include "s3fs_util.h" #include "string_util.h" #include "s3fs_help.h" +#include "autolock.h" //------------------------------------------------------------------- // Global variables @@ -170,8 +171,60 @@ int is_uid_include_group(uid_t uid, gid_t gid) //------------------------------------------------------------------- // Utility for file and directory //------------------------------------------------------------------- +// [NOTE] +// basename/dirname returns a static variable pointer as the return value. +// Normally this shouldn't be a problem, but in macos10 we found a case +// where dirname didn't receive its return value correctly due to thread +// conflicts. +// To avoid this, exclusive control is performed by mutex. +// +static pthread_mutex_t* pbasename_lock = NULL; + +bool init_basename_lock() +{ + if(pbasename_lock){ + S3FS_PRN_ERR("already initialized mutex for posix dirname/basename function."); + return false; + } + pbasename_lock = new pthread_mutex_t; + + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + +#if S3FS_PTHREAD_ERRORCHECK + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); +#endif + int result; + if(0 != (result = pthread_mutex_init(pbasename_lock, &attr))){ + S3FS_PRN_ERR("failed to init pbasename_lock: %d.", result); + delete pbasename_lock; + pbasename_lock = NULL; + return false; + } + return true; +} + +bool destroy_basename_lock() +{ + if(!pbasename_lock){ + S3FS_PRN_ERR("the mutex for posix dirname/basename function is not initialized."); + return false; + } + int result; + if(0 != (result = pthread_mutex_destroy(pbasename_lock))){ + S3FS_PRN_ERR("failed to destroy pbasename_lock: %d", result); + return false; + } + delete pbasename_lock; + pbasename_lock = NULL; + + return true; +} + std::string mydirname(const std::string& path) { + AutoLock auto_lock(pbasename_lock); + return std::string(dirname(const_cast(path.c_str()))); } @@ -187,6 +240,8 @@ std::string mydirname(const char* path) std::string mybasename(const std::string& path) { + AutoLock auto_lock(pbasename_lock); + return std::string(basename(const_cast(path.c_str()))); } diff --git a/src/s3fs_util.h b/src/s3fs_util.h index 5d0757d..243548e 100644 --- a/src/s3fs_util.h +++ b/src/s3fs_util.h @@ -40,6 +40,8 @@ void init_sysconf_vars(); std::string get_username(uid_t uid); int is_uid_include_group(uid_t uid, gid_t gid); +bool init_basename_lock(); +bool destroy_basename_lock(); std::string mydirname(const char* path); std::string mydirname(const std::string& path); std::string mybasename(const char* path);