Skip to content

Commit 0c76f27

Browse files
committed
Only let the owner clean up semaphore and shared memory
I noticed a bug in the semaphore handling, when using the System V semaphore backend: $ LD_PRELOAD=./src/libfaketime.so.1 bash -c "echo foo | sed s/foo/bar/" libfaketime: In lock_for_stat(), ft_sem_lock failed: Invalid argument [...exited with error...] (Beware, the above command-line is not 100% deterministic; sometimes it succeeds.) Looking at the strace for the above command-line, it seems the bash echo builtin process (or thread?) decides to remove the semaphore upon exiting, while it's still in use by the sed process. sed then gets EINVAL error ("Invalid argument") on its next semop call. The root cause is a semantic difference between POSIX sem_unlink and SysV semop(..., IPC_RMID), the two implementations for ft_sem_unlink: * sem_unlink allows the semaphore to be used afterwards, as long as a process has a reference to the semaphore. * semop(..., IPC_RMID) removes the semaphore immediately, and further use results in EINVAL error. AFAICT, the simplest fix is to only let the owner of the semaphore (and shared memory) do the clean up, which is what this patch does. Both semaphore backends pass the tests with this change.
1 parent 7bfe656 commit 0c76f27

File tree

1 file changed

+14
-3
lines changed

1 file changed

+14
-3
lines changed

src/libfaketime.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -697,10 +697,21 @@ static void ft_shm_destroy(void)
697697
*/
698698
if (0 == ft_sem_open(sem_name, &ft_sem))
699699
{
700-
ft_sem_unlink(&ft_sem);
700+
// Only delete the semaphore (and shared memory) if we're the owner.
701+
pid_t sem_owner_pid;
702+
int num_matched = sscanf(sem_name, "/faketime_sem_%d", &sem_owner_pid);
703+
if (num_matched != 1)
704+
{
705+
fprintf(stderr, "libfaketime: failed to parse semaphore owner pid from sem_name %s\n", sem_name);
706+
exit(1);
707+
}
708+
if (getpid() == sem_owner_pid)
709+
{
710+
ft_sem_unlink(&ft_sem);
711+
shm_unlink(shm_name);
712+
unsetenv("FAKETIME_SHARED");
713+
}
701714
}
702-
shm_unlink(shm_name);
703-
unsetenv("FAKETIME_SHARED");
704715
}
705716
}
706717

0 commit comments

Comments
 (0)