]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
When a thread in a nanosleep() wait is interrupted by a non-restartable
authorJulian Seward <jseward@acm.org>
Thu, 6 Jun 2002 01:27:39 +0000 (01:27 +0000)
committerJulian Seward <jseward@acm.org>
Thu, 6 Jun 2002 01:27:39 +0000 (01:27 +0000)
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

coregrind/arch/x86-linux/vg_libpthread.c
coregrind/vg_libpthread.c
coregrind/vg_scheduler.c
vg_libpthread.c
vg_scheduler.c

index 8a74a5c382de9da03a040184c8ee49181dca3910..e575e0a8b358acfdb10ca742d631a937d5dcbbe3 100644 (file)
@@ -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;
+      }
    }
 }
 
index 8a74a5c382de9da03a040184c8ee49181dca3910..e575e0a8b358acfdb10ca742d631a937d5dcbbe3 100644 (file)
@@ -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;
+      }
    }
 }
 
index 4e68b67f80486a593bb6ce405af22163f73e0f50..ee404d29c9ea7fcbcaaebf19abe2f6c763a0768d 100644 (file)
@@ -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;
    }
 
index 8a74a5c382de9da03a040184c8ee49181dca3910..e575e0a8b358acfdb10ca742d631a937d5dcbbe3 100644 (file)
@@ -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;
+      }
    }
 }
 
index 4e68b67f80486a593bb6ce405af22163f73e0f50..ee404d29c9ea7fcbcaaebf19abe2f6c763a0768d 100644 (file)
@@ -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;
    }