Hi, On 2018-08-22 13:02, Андрей Доценко wrote: > Package: libc6 > Version: 2.24-11+deb9-u3 > > Using sem_timedwait on i686 gives random results. In out proprietary > software semaphore used by two processes and located in shared memory > mapped with mmap. All works under amd64 architecture and under another some > distibutions. But under Debian Stretch amd64 sem_timedwait always blocks > for timeout and returns ETIMEOUT error. Meanwhile it acquires the lock > decreasing semaphore value. > > I've tried to make test for this bug. Test reproduces bug only with ASAN > enabled. Without ASAN enabled it always passes. I've attached test but > without ASAN support to show that I don't miss anything. I can modify test > to enable ASAN support but if somebody ask.
Thanks, I have been able to reproduce the problem here, even with glibc 2.29. I have attached a version which doesn't need cmake nor check. On your side, have you been able to reproduce the problem *without* ASAN, even on a bigger codebase? I wonder if it is actually a side effect of ASAN. > I've discovered that symbols used by i686 are different from those from > amd64. On amd64 symbols are: > ~$ nm "${PROJ_PATH}/Docker/debian/9/amd64/test-bugs/test-bugs" | grep sem_ > U sem_destroy@@GLIBC_2.2.5 > U sem_getvalue@@GLIBC_2.2.5 > U sem_init@@GLIBC_2.2.5 > U sem_post@@GLIBC_2.2.5 > U sem_timedwait@@GLIBC_2.2.5 > 00000000004019b0 t test_process_sem_timedwait > 00000000004011c0 t test_process_sem_timedwait_nolock > > But under i686 symbols are different: > ~$ nm "${PROJ_PATH}/Docker/debian/9/i386/test-bugs/test-bugs" | grep sem_ > U sem_destroy@@GLIBC_2.1 > U sem_getvalue@@GLIBC_2.1 > U sem_init@@GLIBC_2.1 > U sem_post@@GLIBC_2.1 > U sem_timedwait@@GLIBC_2.2 > 08049f50 t test_process_sem_timedwait > 08048ee0 t test_process_sem_timedwait_nolock > > As you can see symbols are different for i686. Version of sem_init, > sem_wait, sem_post, sem_destroy and sem_getvalue is GLIBC_2.1, but version > of sem_timedwait is GLIBC_2.2. This is perfectly normal. glibc 2.2.5 is the first glibc version that supported the amd64 architecture. > Replacing sem_timedwait with sem_wait makes all work on i686 architecture. > So sem_wait is ok, but sem_timedwait is not. I confirm that. Regards, Aurelien -- Aurelien Jarno GPG: 4096R/1DDD8C9B aurel...@aurel32.net http://www.aurel32.net
/* Build with: gcc -o bug906917 bug906917.c -pthread -fsanitize=address */ #include <assert.h> #include <errno.h> #include <semaphore.h> #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/wait.h> #include <time.h> #include <unistd.h> int main() { sem_t *sem = mmap(NULL, sizeof(*sem), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); int r; r = sem_init(sem, 1, 0); if (r == -1) { perror("sem_init"); } assert(r == 0); pid_t pid = fork(); if (pid == 0) { r = sem_post(sem); if (r == -1) { exit(1); } exit(0); } assert(pid > 0); int exit_status; pid_t child_pid; do { child_pid = waitpid(pid, &exit_status, 0); } while ((child_pid == -1) && (errno == EINTR)); if (child_pid == -1) { perror("waitpid"); } assert(child_pid == pid); assert(WIFEXITED(exit_status)); assert(WEXITSTATUS(exit_status) == 0); struct timespec abstime; r = clock_gettime(CLOCK_REALTIME, &abstime); assert(r == 0); abstime.tv_sec += 5; int value = -1; sem_getvalue(sem, &value); assert(value == 1); do { r = sem_timedwait(sem, &abstime); } while ((r == -1) && (errno == EINTR)); if (r == -1) { perror("sem_timedwait"); } assert(r == 0); value = -1; sem_getvalue(sem, &value); assert(value == 0); sem_destroy(sem); return 0; }