diff options
| author | Eli Zaretskii | 2012-11-14 18:41:43 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2012-11-14 18:41:43 +0200 |
| commit | 730b2d8f6b5851dc462b79b8bd48068c1b9f1932 (patch) | |
| tree | f608a34a8622871ad0742a2959fc435a94f468b5 /src | |
| parent | 921c067f4309c3eab0aa536723683bada6802545 (diff) | |
| download | emacs-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/ChangeLog | 12 | ||||
| -rw-r--r-- | src/w32proc.c | 38 |
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 @@ | |||
| 1 | 2012-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 | |||
| 1 | 2012-11-13 Jan Djärv <jan.h.d@swipnet.se> | 13 | 2012-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 | |||
| 556 | start_timer_thread (int which) | 557 | start_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; |