diff --git a/source/posix/cross_process_lock.c b/source/posix/cross_process_lock.c index 1e6db0bbb..1ef5d2b5f 100644 --- a/source/posix/cross_process_lock.c +++ b/source/posix/cross_process_lock.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -41,14 +42,20 @@ struct aws_cross_process_lock *aws_cross_process_lock_try_acquire( * The unix standard says /tmp has to be there and be writable. However, while it may be tempting to just use the * /tmp/ directory, it often has the sticky bit set which would prevent a subprocess from being able to call open * with create on the file. The solution is simple, just write it to a subdirectory inside - * /tmp using the same perms as the current process. + * /tmp and override umask via. chmod of 0777. */ struct aws_byte_cursor path_prefix = aws_byte_cursor_from_c_str("/tmp/aws_crt_cross_process_lock/"); struct aws_string *path_to_create = aws_string_new_from_cursor(allocator, &path_prefix); - /* it's probably there already and we don't care if it is. The open will fail and we will handle it there - * if we can't open it due to permissions. */ - aws_directory_create(path_to_create); + + /* It's probably there already and we don't care if it is. */ + if (!aws_directory_exists(path_to_create)) { + /* if this call fails just let it fail on open below. */ + aws_directory_create(path_to_create); + /* bypass umask by setting the perms we actually requested */ + chmod(aws_string_c_str(path_to_create), S_IRWXU | S_IRWXG | S_IRWXO); + } aws_string_destroy(path_to_create); + struct aws_byte_cursor path_suffix = aws_byte_cursor_from_c_str(".lock"); struct aws_byte_buf nonce_buf; @@ -59,16 +66,45 @@ struct aws_cross_process_lock *aws_cross_process_lock_try_acquire( struct aws_cross_process_lock *instance_lock = NULL; + errno = 0; int fd = open((const char *)nonce_buf.buffer, O_CREAT | O_RDWR, 0666); if (fd < 0) { - AWS_LOGF_ERROR( + AWS_LOGF_DEBUG( AWS_LS_COMMON_GENERAL, "static: Lock file %s failed to open with errno %d", (const char *)nonce_buf.buffer, errno); + aws_translate_and_raise_io_error_or(errno, AWS_ERROR_MUTEX_FAILED); - goto cleanup; + + if (aws_last_error() == AWS_ERROR_NO_PERMISSION) { + AWS_LOGF_DEBUG( + AWS_LS_COMMON_GENERAL, + "static: Lock file %s couldn't be opened due to file ownership permissions. Attempting to open as read " + "only", + (const char *)nonce_buf.buffer); + + errno = 0; + fd = open((const char *)nonce_buf.buffer, O_RDONLY); + + if (fd < 0) { + AWS_LOGF_ERROR( + AWS_LS_COMMON_GENERAL, + "static: Lock file %s failed to open with read-only permissions with errno %d", + (const char *)nonce_buf.buffer, + errno); + aws_translate_and_raise_io_error_or(errno, AWS_ERROR_MUTEX_FAILED); + goto cleanup; + } + } else { + AWS_LOGF_ERROR( + AWS_LS_COMMON_GENERAL, + "static: Lock file %s failed to open. The lock cannot be acquired.", + (const char *)nonce_buf.buffer); + goto cleanup; + } } + if (flock(fd, LOCK_EX | LOCK_NB) == -1) { AWS_LOGF_TRACE( AWS_LS_COMMON_GENERAL,