From: Julian Seward Date: Thu, 6 Jun 2002 01:27:39 +0000 (+0000) Subject: When a thread in a nanosleep() wait is interrupted by a non-restartable X-Git-Tag: svn/VALGRIND_1_0_3~82 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=37a139e555e68b201b542aeee488593a1024bc41;p=thirdparty%2Fvalgrind.git When a thread in a nanosleep() wait is interrupted by a non-restartable signal, cause the nanoslep to return with EINTR. Then, in the user-space nonblocking select() implementation, notice this and correspondingly return with EINTR. This appears to fix the MySQL hang-at-exit problem. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@391 --- diff --git a/coregrind/arch/x86-linux/vg_libpthread.c b/coregrind/arch/x86-linux/vg_libpthread.c index 8a74a5c382..e575e0a8b3 100644 --- a/coregrind/arch/x86-linux/vg_libpthread.c +++ b/coregrind/arch/x86-linux/vg_libpthread.c @@ -1909,8 +1909,14 @@ int select ( int n, nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */ /* It's critical here that valgrind's nanosleep implementation is nonblocking. */ - (void)my_do_syscall2(__NR_nanosleep, + res = my_do_syscall2(__NR_nanosleep, (int)(&nanosleep_interval), (int)NULL); + if (res == -VKI_EINTR) { + /* The nanosleep was interrupted by a signal. So we do the + same. */ + * (__errno_location()) = EINTR; + return -1; + } } } diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c index 8a74a5c382..e575e0a8b3 100644 --- a/coregrind/vg_libpthread.c +++ b/coregrind/vg_libpthread.c @@ -1909,8 +1909,14 @@ int select ( int n, nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */ /* It's critical here that valgrind's nanosleep implementation is nonblocking. */ - (void)my_do_syscall2(__NR_nanosleep, + res = my_do_syscall2(__NR_nanosleep, (int)(&nanosleep_interval), (int)NULL); + if (res == -VKI_EINTR) { + /* The nanosleep was interrupted by a signal. So we do the + same. */ + * (__errno_location()) = EINTR; + return -1; + } } } diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index 4e68b67f80..ee404d29c9 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -63,6 +63,9 @@ TODO sometime: +- poll() in the vg_libpthread.c -- should it handle the nanosleep + being interrupted by a signal? Ditto accept? + - Mutex scrubbing - clearup_after_thread_exit: look for threads blocked on mutexes held by the exiting thread, and release them appropriately. (??) @@ -794,6 +797,7 @@ void handle_signal_return ( ThreadId tid ) { Char msg_buf[100]; Bool restart_blocked_syscalls; + struct vki_timespec * rem; vg_assert(VG_(is_valid_tid)(tid)); @@ -819,11 +823,19 @@ void handle_signal_return ( ThreadId tid ) return; } - if (VG_(threads)[tid].status == VgTs_WaitFD + if (VG_(threads)[tid].status == VgTs_Sleeping && VG_(threads)[tid].m_eax == __NR_nanosleep) { /* We interrupted a nanosleep(). The right thing to do is to - write the unused time to nanosleep's second param and return - EINTR, but I'm too lazy for that. */ + write the unused time to nanosleep's second param, but that's + too much effort ... we just say that 1 nanosecond was not + used, and return EINTR. */ + rem = (struct vki_timespec *)VG_(threads)[tid].m_ecx; /* arg2 */ + if (rem != NULL) { + rem->tv_sec = 0; + rem->tv_nsec = 1; + } + SET_EAX(tid, -VKI_EINTR); + VG_(threads)[tid].status = VgTs_Runnable; return; } diff --git a/vg_libpthread.c b/vg_libpthread.c index 8a74a5c382..e575e0a8b3 100644 --- a/vg_libpthread.c +++ b/vg_libpthread.c @@ -1909,8 +1909,14 @@ int select ( int n, nanosleep_interval.tv_nsec = 50 * 1000 * 1000; /* 50 milliseconds */ /* It's critical here that valgrind's nanosleep implementation is nonblocking. */ - (void)my_do_syscall2(__NR_nanosleep, + res = my_do_syscall2(__NR_nanosleep, (int)(&nanosleep_interval), (int)NULL); + if (res == -VKI_EINTR) { + /* The nanosleep was interrupted by a signal. So we do the + same. */ + * (__errno_location()) = EINTR; + return -1; + } } } diff --git a/vg_scheduler.c b/vg_scheduler.c index 4e68b67f80..ee404d29c9 100644 --- a/vg_scheduler.c +++ b/vg_scheduler.c @@ -63,6 +63,9 @@ TODO sometime: +- poll() in the vg_libpthread.c -- should it handle the nanosleep + being interrupted by a signal? Ditto accept? + - Mutex scrubbing - clearup_after_thread_exit: look for threads blocked on mutexes held by the exiting thread, and release them appropriately. (??) @@ -794,6 +797,7 @@ void handle_signal_return ( ThreadId tid ) { Char msg_buf[100]; Bool restart_blocked_syscalls; + struct vki_timespec * rem; vg_assert(VG_(is_valid_tid)(tid)); @@ -819,11 +823,19 @@ void handle_signal_return ( ThreadId tid ) return; } - if (VG_(threads)[tid].status == VgTs_WaitFD + if (VG_(threads)[tid].status == VgTs_Sleeping && VG_(threads)[tid].m_eax == __NR_nanosleep) { /* We interrupted a nanosleep(). The right thing to do is to - write the unused time to nanosleep's second param and return - EINTR, but I'm too lazy for that. */ + write the unused time to nanosleep's second param, but that's + too much effort ... we just say that 1 nanosecond was not + used, and return EINTR. */ + rem = (struct vki_timespec *)VG_(threads)[tid].m_ecx; /* arg2 */ + if (rem != NULL) { + rem->tv_sec = 0; + rem->tv_nsec = 1; + } + SET_EAX(tid, -VKI_EINTR); + VG_(threads)[tid].status = VgTs_Runnable; return; }