]> git.eshelyaron.com Git - emacs.git/commitdiff
Clean up w32 timer thread code in the hope of solving bug #12832.
authorEli Zaretskii <eliz@gnu.org>
Wed, 14 Nov 2012 16:41:43 +0000 (18:41 +0200)
committerEli Zaretskii <eliz@gnu.org>
Wed, 14 Nov 2012 16:41:43 +0000 (18:41 +0200)
 src/w32proc.c (timer_loop): Make sure SuspendThread and ResumeThread
 use the same value of thread handle.
 (start_timer_thread): If the timer thread exited (due to error),
 clean up by closing the two handles it used.  Duplicate the caller
 thread's handle here, so it gets duplicated only once, when
 launching the timer thread.  Set priority of the timer thread, not
 the caller thread.
 (getitimer): Don't duplicate the caller thread's handle here.

src/ChangeLog
src/w32proc.c

index d72091c0ed65686555e5b178482b8f6dc74bc3bc..9caa5113444e0458405fc456baaa2c0ee840a879 100644 (file)
@@ -1,3 +1,15 @@
+2012-11-14  Eli Zaretskii  <eliz@gnu.org>
+
+       * w32proc.c (timer_loop): Make sure SuspendThread and ResumeThread
+       use the same value of thread handle.
+       (start_timer_thread): If the timer thread exited (due to error),
+       clean up by closing the two handles it used.  Duplicate the caller
+       thread's handle here, so it gets duplicated only once, when
+       launching the timer thread.  Set priority of the timer thread, not
+       the caller thread.
+       (getitimer): Don't duplicate the caller thread's handle here.
+       (Bug#12832)
+
 2012-11-13  Jan Djärv  <jan.h.d@swipnet.se>
 
        * nsterm.m (hold_event): Send SIGIO to make sure ns_read_socket is
index adef7651b8ce50097d790256ba10bed2477f361e..e3c54fe54600e584df85d50d2d922d6b9fa4f431 100644 (file)
@@ -425,13 +425,14 @@ timer_loop (LPVOID arg)
          /* Simulate a signal delivered to the thread which installed
             the timer, by suspending that thread while the handler
             runs.  */
-         DWORD result = SuspendThread (itimer->caller_thread);
+         HANDLE th = itimer->caller_thread;
+         DWORD result = SuspendThread (th);
 
          if (result == (DWORD)-1)
            return 2;
 
          handler (sig);
-         ResumeThread (itimer->caller_thread);
+         ResumeThread (th);
        }
 
       /* Update expiration time and loop.  */
@@ -556,6 +557,7 @@ static int
 start_timer_thread (int which)
 {
   DWORD exit_code;
+  HANDLE th;
   struct itimer_data *itimer =
     (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
 
@@ -564,9 +566,29 @@ start_timer_thread (int which)
       && exit_code == STILL_ACTIVE)
     return 0;
 
+  /* Clean up after possibly exited thread.  */
+  if (itimer->timer_thread)
+    {
+      CloseHandle (itimer->timer_thread);
+      itimer->timer_thread = NULL;
+    }
+  if (itimer->caller_thread)
+    {
+      CloseHandle (itimer->caller_thread);
+      itimer->caller_thread = NULL;
+    }
+
   /* Start a new thread.  */
+  if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
+                       GetCurrentProcess (), &th, 0, FALSE,
+                       DUPLICATE_SAME_ACCESS))
+    {
+      errno = ESRCH;
+      return -1;
+    }
   itimer->terminate = 0;
   itimer->type = which;
+  itimer->caller_thread = th;
   /* Request that no more than 64KB of stack be reserved for this
      thread, to avoid reserving too much memory, which would get in
      the way of threads we start to wait for subprocesses.  See also
@@ -585,7 +607,7 @@ start_timer_thread (int which)
   /* This is needed to make sure that the timer thread running for
      profiling gets CPU as soon as the Sleep call terminates. */
   if (which == ITIMER_PROF)
-    SetThreadPriority (itimer->caller_thread, THREAD_PRIORITY_TIME_CRITICAL);
+    SetThreadPriority (itimer->timer_thread, THREAD_PRIORITY_TIME_CRITICAL);
 
   return 0;
 }
@@ -620,17 +642,9 @@ getitimer (int which, struct itimerval *value)
 
   itimer = (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
 
-  if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
-                       GetCurrentProcess (), &itimer->caller_thread, 0,
-                       FALSE, DUPLICATE_SAME_ACCESS))
-    {
-      errno = ESRCH;
-      return -1;
-    }
-
   ticks_now = w32_get_timer_time ((which == ITIMER_REAL)
                                  ? NULL
-                                 : itimer->caller_thread);
+                                 : GetCurrentThread ());
 
   t_expire = &itimer->expire;
   t_reload = &itimer->reload;