On Thu, Jan 02, 2025 at 01:19:38AM +0100, Alejandro Colomar wrote: > [CC += libc-help] > > Hi Arkadiusz, > > On Wed, Jan 01, 2025 at 11:20:26PM +0100, Arkadiusz Drabczyk wrote: > > In man/man7/signal.7 it says: > > > > > If a blocked call to one of the following interfaces is interrupted > > > by a signal handler, then the call is automatically restarted after > > > the signal handler returns if the SA_RESTART flag was used; > > > otherwise the call fails with the error EINTR: > > > (...) > > > • pthread_mutex_lock(3), pthread_cond_wait(3), and related APIs. > > > > I don't understand this, in my experiments neither > > pthread_mutex_lock() nor pthread_cond_wait() return EINTR even if > > signal handler was installed without using SA_RESTART flag. > > Please show some minimal examples if you can. Here is the minimal example for pthread_mutex_lock() with all checks: #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> #include <signal.h> #include <string.h> #include <stdint.h> pthread_mutex_t m; void handle_sigint(int sig) { (void)sig; write(STDOUT_FILENO, "SIGINT", 6); } void *example_thread(void *arg) { (void)arg; int ret = pthread_mutex_lock(&m); if (ret) { fprintf(stderr, "pthread_mutex_lock: %s\n", strerror(ret)); return NULL; } puts("Mutex acquired in thread"); sleep(3600); ret = pthread_mutex_unlock(&m); if (ret) fprintf(stderr, "pthread_mutex_unlock: %s\n", strerror(ret)); return NULL; } int main(void) { struct sigaction sa; pthread_t thread; int ret = 0; int main_ret = 0; int destroy_mutex = 1; sa.sa_handler = handle_sigint; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); if (sigaction(SIGINT, &sa, NULL) == -1) { perror("sigaction"); return EXIT_FAILURE; } pthread_mutex_init(&m, NULL); ret = pthread_create(&thread, NULL, example_thread, NULL); if (ret) { fprintf(stderr, "pthread_create: %s\n", strerror(ret)); main_ret = ret; goto out; } sleep(3); printf("Wait for mutex in main thread, send INT to process %jd now\n", (intmax_t) getpid()); ret = pthread_mutex_lock(&m); if (ret) { fprintf(stderr, "pthread_mutex_lock: %s\n", strerror(ret)); main_ret = ret; goto join; } puts("Got mutex in main thread"); ret = pthread_mutex_unlock(&m); if (ret) { fprintf(stderr, "pthread_mutex_unlock: %s\n", strerror(ret)); main_ret = ret; destroy_mutex = 0; goto join; } join: ret = pthread_join(thread, NULL); if (ret) { fprintf(stderr, "pthread_join: %s\n", strerror(ret)); return EXIT_FAILURE; } out: if (destroy_mutex) { ret = pthread_mutex_destroy(&m); if (ret) { fprintf(stderr, "pthread_mutex_destroy: %s\n", strerror(ret)); return EXIT_FAILURE; } } return main_ret; } > Arkadiusz, would you do the honours writing a patch? Should I? I could do that but there is one more problem here - most pthread manpages mention EINTR only to say that they don't return it except pthread_cond_init.3: $ find . -name "*pthread*" -print0 | xargs -0 grep EINTR ./man/man3/pthread_atfork.3:.BR EINTR . ./man/man3/pthread_tryjoin_np.3:.BR EINTR . ./man/man3/pthread_cond_init.3:\fBEINTR\fP ./man/man7/pthreads.7:.BR EINTR . that says: > EINTR pthread_cond_timedwait was interrupted by a signal. It's hard to say if it ever really worked like that because in man/man7/pthreads.7 it says that no EINTR has been the requirement since 2001: > Most pthreads functions return 0 on success, and an error number on > failure. The error numbers that can be returned have the same meaning > as the error numbers returned in errno by conventional system calls > and C library functions. Note that the pthreads functions do not set > errno. For each of the pthreads functions that can return an error, > POSIX.1-2001 specifies that the function can never fail with the error > EINTR. Today POSIX still says that pthread_cond_timedwait() cannot return EINTR https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_cond_clockwait.html and in my experiments it really doesn't, both with glibc and musl. pthread_cond_init.3 has been added in 1998 under linuxthread/ directory, maybe the behavior specified by POSIX was different than the initial design but OTOH it's quite surprising that no one noticed the bug for so many years, I wonder how many people still check for EINTR in pthread_cond_timedwait even though it's not necessary (but harmless). So I was thinking that "pthread_mutex_lock(3), pthread_cond_wait(3), and related APIs." line could be completely removed from signal.7 because there is no pthread API that would return EINTR and EINTR should be removed from the list of valid error codes in pthread_cond_init.3. Does it sound good? -- Arkadiusz Drabczyk <arkadiusz@xxxxxxxxxxxx>