libfaketime hangs forever when 32-bit process is executed within 64-bit process
libfaketime seems to hang forever when a 32-bit process is started when libfaketime is available for 64 and 32-bit
Tested using 0.9.10
steps to reproduce:
1: build libfaketime for both 32 and 64-bit
make clean
CFLAGS="-m32" LDFLAGS="-m32" make
mv src/libfaketime.so.1 /lib/libfaketime.so
make clean
make
mv src/libfaketime.so.1 /lib64/libfaketime.so
2: build 32-bit example
test.c
#include <stdio.h>
int main() {
printf("Hello, World!");
return 0;
}
compile:
gcc -m32 test.c -o test
3: run
starting the 32-bit process:
LD_PRELOAD=libfaketime.so FAKETIME=+60d ./test
Hello, World!
when trying to start from within a 64-bit process, it hangs forever:
LD_PRELOAD=libfaketime.so FAKETIME=+60d bash -c ./test
output from gdb, attached to the 32-bit process:
(gdb) bt
#0 0xf7f03549 in __kernel_vsyscall ()
#1 0xf7d07b3c in do_futex_wait.constprop () from /lib/libpthread.so.0
#2 0xf7d07c27 in __new_sem_wait_slow.constprop.1 () from /lib/libpthread.so.0
#3 0xf7ee90e4 in ftpl_init () from /lib/libfaketime.so
#4 0xf7f14fce in _dl_init_internal () from /lib/ld-linux.so.2
#5 0xf7f0618f in _dl_start_user () from /lib/ld-linux.so.2
output from strace:
statfs("/dev/shm", {f_type=TMPFS_MAGIC, f_bsize=4096, f_blocks=16384, f_bfree=16360, f_bavail=16360, f_files=1018431, f_ffree=1018406, f_fsid={val=[0, 0]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_NOSUID|ST_NODEV|ST_NOEXEC|ST_RELATIME}) = 0
futex(0xf7d4e1a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
open("/dev/shm/sem.faketime_sem_19240", O_RDWR|O_NOFOLLOW) = 3
fstat64(3, {st_mode=S_IFREG|0600, st_size=32, ...}) = 0
mmap2(NULL, 16, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0) = 0xf7f36000
close(3) = 0
munmap(0xf7f36000, 16) = 0
open("/dev/shm/sem.faketime_sem_19240", O_RDWR|O_NOFOLLOW) = 3
fstat64(3, {st_mode=S_IFREG|0600, st_size=32, ...}) = 0
mmap2(NULL, 16, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0) = 0xf7f36000
close(3) = 0
statfs("/dev/shm/", {f_type=TMPFS_MAGIC, f_bsize=4096, f_blocks=16384, f_bfree=16360, f_bavail=16360, f_files=1018431, f_ffree=1018406, f_fsid={val=[0, 0]}, f_namelen=255, f_frsize=4096, f_flags=ST_VALID|ST_NOSUID|ST_NODEV|ST_NOEXEC|ST_RELATIME}) = 0
futex(0xf7ceb1d0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
open("/dev/shm/faketime_shm_19240", O_RDWR|O_CREAT|O_NOFOLLOW|O_CLOEXEC, 0600) = 3
mmap2(NULL, 48, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0) = 0xf7f35000
futex(0xf7f36000, FUTEX_WAIT_PRIVATE, 1, NULL
it seems the process is using the shared shm/sem from the parent process (19240) this is broken since 0.9.8, in which FAKETIME_SHARED is used for passing the semaphore and shared memory.
Thanks for reporting. Might be related to how the struct timespec is defined on the system for 32 vs 64 bit processes, as it is used as a part of the shared memory libfaketime uses.
As a workaround, does it help to explicitly unset FAKETIME_SHARED before starting the child process? Also, I assume this only happens when already the parent process is started with libfaketime preloaded?
correct! issue only occurs when libfaketime is loaded in the parent process using LD_PRELOAD. explicitly unsetting FAKETIME_SHARED resolves the issue for the example:
LD_PRELOAD=libfaketime.so FAKETIME=+60d bash -c 'unset FAKETIME_SHARED; ./test'
Hello, World!
This however is not a workaround for me as the child process in my use-case is a 32-bit python interpreter started from pyenv. I have no control on when the 32-bit process is started. This can also be the case for other applications in which a 32-bit process is used.
Maybe add an option to not share sem/shm? for example by setting FAKETIME_SHARED=0?
For now I will stick to 0.9.7 which is working without problem