Skip to content

Commit 3f75433

Browse files
tyan0github-cygwin
authored andcommitted
Cygwin: cygwait: Make cygwait() reentrant
To allow cygwait() to be called in the signal handler, a locally created timer is used instead of _cygtls::locals.cw_timer if it is in use. Co-Authored-By: Corinna Vinschen <[email protected]> Signed-off-by: Takashi Yano <[email protected]>
1 parent 6eaf264 commit 3f75433

File tree

4 files changed

+35
-14
lines changed

4 files changed

+35
-14
lines changed

winsup/cygwin/cygtls.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ _cygtls::init_thread (void *x, DWORD (*func) (void *, void *))
6464
initialized = CYGTLS_INITIALIZED;
6565
errno_addr = &(local_clib._errno);
6666
locals.cw_timer = NULL;
67+
locals.cw_timer_inuse = false;
6768
locals.pathbufs.clear ();
6869

6970
if ((void *) func == (void *) cygthread::stub
@@ -85,6 +86,7 @@ _cygtls::fixup_after_fork ()
8586
signal_arrived = NULL;
8687
locals.select.sockevt = NULL;
8788
locals.cw_timer = NULL;
89+
locals.cw_timer_inuse = false;
8890
locals.pathbufs.clear ();
8991
wq.thread_ev = NULL;
9092
}

winsup/cygwin/cygwait.cc

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,21 @@ cygwait (HANDLE object, PLARGE_INTEGER timeout, unsigned mask)
5858
}
5959

6060
DWORD timeout_n;
61+
HANDLE *wait_timer = &_my_tls.locals.cw_timer;
62+
HANDLE local_wait_timer = NULL;
6163
if (!timeout)
6264
timeout_n = WAIT_TIMEOUT + 1;
6365
else
6466
{
67+
if (_my_tls.locals.cw_timer_inuse)
68+
wait_timer = &local_wait_timer;
69+
else
70+
_my_tls.locals.cw_timer_inuse = true;
6571
timeout_n = WAIT_OBJECT_0 + num++;
66-
if (!_my_tls.locals.cw_timer)
67-
NtCreateTimer (&_my_tls.locals.cw_timer, TIMER_ALL_ACCESS, NULL,
68-
NotificationTimer);
69-
NtSetTimer (_my_tls.locals.cw_timer, timeout, NULL, NULL, FALSE, 0, NULL);
70-
wait_objects[timeout_n] = _my_tls.locals.cw_timer;
72+
if (!*wait_timer)
73+
NtCreateTimer (wait_timer, TIMER_ALL_ACCESS, NULL, NotificationTimer);
74+
NtSetTimer (*wait_timer, timeout, NULL, NULL, FALSE, 0, NULL);
75+
wait_objects[timeout_n] = *wait_timer;
7176
}
7277

7378
while (1)
@@ -100,15 +105,19 @@ cygwait (HANDLE object, PLARGE_INTEGER timeout, unsigned mask)
100105
{
101106
TIMER_BASIC_INFORMATION tbi;
102107

103-
NtQueryTimer (_my_tls.locals.cw_timer, TimerBasicInformation, &tbi,
108+
NtQueryTimer (*wait_timer, TimerBasicInformation, &tbi,
104109
sizeof tbi, NULL);
105110
/* if timer expired, TimeRemaining is negative and represents the
106111
system uptime when signalled */
107112
if (timeout->QuadPart < 0LL) {
108113
timeout->QuadPart = tbi.SignalState || tbi.TimeRemaining.QuadPart < 0LL
109114
? 0LL : tbi.TimeRemaining.QuadPart;
110115
}
111-
NtCancelTimer (_my_tls.locals.cw_timer, NULL);
116+
NtCancelTimer (*wait_timer, NULL);
117+
if (local_wait_timer)
118+
NtClose(local_wait_timer);
119+
else
120+
_my_tls.locals.cw_timer_inuse = false;
112121
}
113122

114123
if (res == WAIT_CANCELED && is_cw_cancel_self)

winsup/cygwin/local_includes/cygtls.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ struct _local_storage
135135

136136
/* thread.cc */
137137
HANDLE cw_timer;
138+
bool cw_timer_inuse;
138139

139140
tls_pathbuf pathbufs;
140141
char ttybuf[32];
@@ -180,7 +181,7 @@ class _cygtls
180181
siginfo_t *sigwait_info;
181182
HANDLE signal_arrived;
182183
bool will_wait_for_signal;
183-
#if 0
184+
#if 1
184185
long __align; /* Needed to align context to 16 byte. */
185186
#endif
186187
/* context MUST be aligned to 16 byte, otherwise RtlCaptureContext fails.

winsup/cygwin/select.cc

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -385,13 +385,18 @@ next_while:;
385385
to create the timer once per thread. Since WFMO checks the handles
386386
in order, we append the timer as last object, otherwise it's preferred
387387
over actual events on the descriptors. */
388-
HANDLE &wait_timer = _my_tls.locals.cw_timer;
388+
HANDLE *wait_timer = &_my_tls.locals.cw_timer;
389+
HANDLE local_wait_timer = NULL;
389390
if (us > 0LL)
390391
{
391392
NTSTATUS status;
392-
if (!wait_timer)
393+
if (_my_tls.locals.cw_timer_inuse)
394+
wait_timer = &local_wait_timer;
395+
else
396+
_my_tls.locals.cw_timer_inuse = true;
397+
if (!*wait_timer)
393398
{
394-
status = NtCreateTimer (&wait_timer, TIMER_ALL_ACCESS, NULL,
399+
status = NtCreateTimer (wait_timer, TIMER_ALL_ACCESS, NULL,
395400
NotificationTimer);
396401
if (!NT_SUCCESS (status))
397402
{
@@ -400,15 +405,15 @@ next_while:;
400405
}
401406
}
402407
LARGE_INTEGER ms_clock_ticks = { .QuadPart = -us * 10 };
403-
status = NtSetTimer (wait_timer, &ms_clock_ticks, NULL, NULL, FALSE,
408+
status = NtSetTimer (*wait_timer, &ms_clock_ticks, NULL, NULL, FALSE,
404409
0, NULL);
405410
if (!NT_SUCCESS (status))
406411
{
407412
select_printf ("%y = NtSetTimer (%D)\n",
408413
status, ms_clock_ticks.QuadPart);
409414
return select_error;
410415
}
411-
w4[m] = wait_timer;
416+
w4[m] = *wait_timer;
412417
timer_idx = m++;
413418
}
414419

@@ -430,7 +435,11 @@ next_while:;
430435
if (timer_idx)
431436
{
432437
BOOLEAN current_state;
433-
NtCancelTimer (wait_timer, &current_state);
438+
NtCancelTimer (*wait_timer, &current_state);
439+
if (local_wait_timer)
440+
NtClose (local_wait_timer);
441+
else
442+
_my_tls.locals.cw_timer_inuse = false;
434443
}
435444

436445
wait_states res;

0 commit comments

Comments
 (0)