diff --git a/src/adapters/asl_pointer_fs/asl_pointer_fs.c b/src/adapters/asl_pointer_fs/asl_pointer_fs.c index 1e1fcb4..2b3d1be 100644 --- a/src/adapters/asl_pointer_fs/asl_pointer_fs.c +++ b/src/adapters/asl_pointer_fs/asl_pointer_fs.c @@ -635,13 +635,13 @@ amduat_asl_pointer_error_t amduat_asl_pointer_cas( const amduat_reference_t *new_ref, bool *out_swapped) { char *head_path = NULL; - int fd = -1; + int lock_fd = -1; struct flock lock; bool exists = false; amduat_reference_t current_ref; amduat_reference_t prev_ref; bool has_prev = false; - bool created = false; + char *lock_path = NULL; amduat_asl_pointer_error_t err; if (out_swapped == NULL) { @@ -663,8 +663,18 @@ amduat_asl_pointer_error_t amduat_asl_pointer_cas( return AMDUAT_ASL_POINTER_ERR_IO; } - fd = open(head_path, O_RDWR | O_CREAT, 0644); - if (fd < 0) { + lock_path = (char *)malloc(strlen(head_path) + sizeof(".lock")); + if (lock_path == NULL) { + free(head_path); + return AMDUAT_ASL_POINTER_ERR_IO; + } + snprintf(lock_path, strlen(head_path) + sizeof(".lock"), "%s.lock", + head_path); + + /* Lock a stable sidecar file so lock ownership survives head-file renames. */ + lock_fd = open(lock_path, O_RDWR | O_CREAT, 0644); + if (lock_fd < 0) { + free(lock_path); free(head_path); return AMDUAT_ASL_POINTER_ERR_IO; } @@ -674,19 +684,13 @@ amduat_asl_pointer_error_t amduat_asl_pointer_cas( lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; - if (fcntl(fd, F_SETLKW, &lock) != 0) { - close(fd); + if (fcntl(lock_fd, F_SETLKW, &lock) != 0) { + close(lock_fd); + free(lock_path); free(head_path); return AMDUAT_ASL_POINTER_ERR_IO; } - { - struct stat st; - if (fstat(fd, &st) == 0 && st.st_size == 0) { - created = true; - } - } - err = amduat_asl_pointer_read_head(head_path, name, &exists, ¤t_ref, &prev_ref, &has_prev); if (err == AMDUAT_ASL_POINTER_ERR_NOT_FOUND) { @@ -694,24 +698,21 @@ amduat_asl_pointer_error_t amduat_asl_pointer_cas( err = AMDUAT_ASL_POINTER_OK; } if (err != AMDUAT_ASL_POINTER_OK) { - close(fd); + close(lock_fd); + free(lock_path); free(head_path); return err; } if (expected_exists != exists) { - if (created) { - (void)unlink(head_path); - } - close(fd); + close(lock_fd); + free(lock_path); free(head_path); return AMDUAT_ASL_POINTER_OK; } if (expected_exists && !amduat_reference_eq(*expected_ref, current_ref)) { - if (created) { - (void)unlink(head_path); - } - close(fd); + close(lock_fd); + free(lock_path); free(head_path); return AMDUAT_ASL_POINTER_OK; } @@ -729,7 +730,8 @@ amduat_asl_pointer_error_t amduat_asl_pointer_cas( if (has_prev) { amduat_reference_free(&prev_ref); } - close(fd); + close(lock_fd); + free(lock_path); free(head_path); return err; }