aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2012-11-14 18:41:43 +0200
committerEli Zaretskii2012-11-14 18:41:43 +0200
commit730b2d8f6b5851dc462b79b8bd48068c1b9f1932 (patch)
treef608a34a8622871ad0742a2959fc435a94f468b5 /src
parent921c067f4309c3eab0aa536723683bada6802545 (diff)
downloademacs-730b2d8f6b5851dc462b79b8bd48068c1b9f1932.tar.gz
emacs-730b2d8f6b5851dc462b79b8bd48068c1b9f1932.zip
Clean up w32 timer thread code in the hope of solving bug #12832.
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.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog12
-rw-r--r--src/w32proc.c38
2 files changed, 38 insertions, 12 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index d72091c0ed6..9caa5113444 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,15 @@
12012-11-14 Eli Zaretskii <eliz@gnu.org>
2
3 * w32proc.c (timer_loop): Make sure SuspendThread and ResumeThread
4 use the same value of thread handle.
5 (start_timer_thread): If the timer thread exited (due to error),
6 clean up by closing the two handles it used. Duplicate the caller
7 thread's handle here, so it gets duplicated only once, when
8 launching the timer thread. Set priority of the timer thread, not
9 the caller thread.
10 (getitimer): Don't duplicate the caller thread's handle here.
11 (Bug#12832)
12
12012-11-13 Jan Djärv <jan.h.d@swipnet.se> 132012-11-13 Jan Djärv <jan.h.d@swipnet.se>
2 14
3 * nsterm.m (hold_event): Send SIGIO to make sure ns_read_socket is 15 * nsterm.m (hold_event): Send SIGIO to make sure ns_read_socket is
diff --git a/src/w32proc.c b/src/w32proc.c
index adef7651b8c..e3c54fe5460 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -425,13 +425,14 @@ timer_loop (LPVOID arg)
425 /* Simulate a signal delivered to the thread which installed 425 /* Simulate a signal delivered to the thread which installed
426 the timer, by suspending that thread while the handler 426 the timer, by suspending that thread while the handler
427 runs. */ 427 runs. */
428 DWORD result = SuspendThread (itimer->caller_thread); 428 HANDLE th = itimer->caller_thread;
429 DWORD result = SuspendThread (th);
429 430
430 if (result == (DWORD)-1) 431 if (result == (DWORD)-1)
431 return 2; 432 return 2;
432 433
433 handler (sig); 434 handler (sig);
434 ResumeThread (itimer->caller_thread); 435 ResumeThread (th);
435 } 436 }
436 437
437 /* Update expiration time and loop. */ 438 /* Update expiration time and loop. */
@@ -556,6 +557,7 @@ static int
556start_timer_thread (int which) 557start_timer_thread (int which)
557{ 558{
558 DWORD exit_code; 559 DWORD exit_code;
560 HANDLE th;
559 struct itimer_data *itimer = 561 struct itimer_data *itimer =
560 (which == ITIMER_REAL) ? &real_itimer : &prof_itimer; 562 (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
561 563
@@ -564,9 +566,29 @@ start_timer_thread (int which)
564 && exit_code == STILL_ACTIVE) 566 && exit_code == STILL_ACTIVE)
565 return 0; 567 return 0;
566 568
569 /* Clean up after possibly exited thread. */
570 if (itimer->timer_thread)
571 {
572 CloseHandle (itimer->timer_thread);
573 itimer->timer_thread = NULL;
574 }
575 if (itimer->caller_thread)
576 {
577 CloseHandle (itimer->caller_thread);
578 itimer->caller_thread = NULL;
579 }
580
567 /* Start a new thread. */ 581 /* Start a new thread. */
582 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
583 GetCurrentProcess (), &th, 0, FALSE,
584 DUPLICATE_SAME_ACCESS))
585 {
586 errno = ESRCH;
587 return -1;
588 }
568 itimer->terminate = 0; 589 itimer->terminate = 0;
569 itimer->type = which; 590 itimer->type = which;
591 itimer->caller_thread = th;
570 /* Request that no more than 64KB of stack be reserved for this 592 /* Request that no more than 64KB of stack be reserved for this
571 thread, to avoid reserving too much memory, which would get in 593 thread, to avoid reserving too much memory, which would get in
572 the way of threads we start to wait for subprocesses. See also 594 the way of threads we start to wait for subprocesses. See also
@@ -585,7 +607,7 @@ start_timer_thread (int which)
585 /* This is needed to make sure that the timer thread running for 607 /* This is needed to make sure that the timer thread running for
586 profiling gets CPU as soon as the Sleep call terminates. */ 608 profiling gets CPU as soon as the Sleep call terminates. */
587 if (which == ITIMER_PROF) 609 if (which == ITIMER_PROF)
588 SetThreadPriority (itimer->caller_thread, THREAD_PRIORITY_TIME_CRITICAL); 610 SetThreadPriority (itimer->timer_thread, THREAD_PRIORITY_TIME_CRITICAL);
589 611
590 return 0; 612 return 0;
591} 613}
@@ -620,17 +642,9 @@ getitimer (int which, struct itimerval *value)
620 642
621 itimer = (which == ITIMER_REAL) ? &real_itimer : &prof_itimer; 643 itimer = (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
622 644
623 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
624 GetCurrentProcess (), &itimer->caller_thread, 0,
625 FALSE, DUPLICATE_SAME_ACCESS))
626 {
627 errno = ESRCH;
628 return -1;
629 }
630
631 ticks_now = w32_get_timer_time ((which == ITIMER_REAL) 645 ticks_now = w32_get_timer_time ((which == ITIMER_REAL)
632 ? NULL 646 ? NULL
633 : itimer->caller_thread); 647 : GetCurrentThread ());
634 648
635 t_expire = &itimer->expire; 649 t_expire = &itimer->expire;
636 t_reload = &itimer->reload; 650 t_reload = &itimer->reload;