Skip to content

Commit 9f9cfe9

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]> (cherry picked from commit ea19140)
1 parent 7d86307 commit 9f9cfe9

File tree

4 files changed

+28
-9
lines changed

4 files changed

+28
-9
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: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,20 @@ cygwait (HANDLE object, PLARGE_INTEGER timeout, unsigned mask)
5858
}
5959

6060
DWORD timeout_n;
61+
HANDLE local_timer = NULL;
62+
HANDLE &wait_timer =
63+
_my_tls.locals.cw_timer_inuse ? local_timer : _my_tls.locals.cw_timer;
6164
if (!timeout)
6265
timeout_n = WAIT_TIMEOUT + 1;
6366
else
6467
{
68+
if (!_my_tls.locals.cw_timer_inuse)
69+
_my_tls.locals.cw_timer_inuse = true;
6570
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;
71+
if (!wait_timer)
72+
NtCreateTimer (&wait_timer, TIMER_ALL_ACCESS, NULL, NotificationTimer);
73+
NtSetTimer (wait_timer, timeout, NULL, NULL, FALSE, 0, NULL);
74+
wait_objects[timeout_n] = wait_timer;
7175
}
7276

7377
while (1)
@@ -100,15 +104,19 @@ cygwait (HANDLE object, PLARGE_INTEGER timeout, unsigned mask)
100104
{
101105
TIMER_BASIC_INFORMATION tbi;
102106

103-
NtQueryTimer (_my_tls.locals.cw_timer, TimerBasicInformation, &tbi,
107+
NtQueryTimer (wait_timer, TimerBasicInformation, &tbi,
104108
sizeof tbi, NULL);
105109
/* if timer expired, TimeRemaining is negative and represents the
106110
system uptime when signalled */
107111
if (timeout->QuadPart < 0LL) {
108112
timeout->QuadPart = tbi.SignalState || tbi.TimeRemaining.QuadPart < 0LL
109113
? 0LL : tbi.TimeRemaining.QuadPart;
110114
}
111-
NtCancelTimer (_my_tls.locals.cw_timer, NULL);
115+
NtCancelTimer (wait_timer, NULL);
116+
if (local_timer)
117+
NtClose(local_timer);
118+
else
119+
_my_tls.locals.cw_timer_inuse = false;
112120
}
113121

114122
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: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,14 @@ 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 local_timer = NULL;
389+
HANDLE &wait_timer =
390+
_my_tls.locals.cw_timer_inuse ? local_timer : _my_tls.locals.cw_timer;
389391
if (us > 0LL)
390392
{
391393
NTSTATUS status;
394+
if (!_my_tls.locals.cw_timer_inuse)
395+
_my_tls.locals.cw_timer_inuse = true;
392396
if (!wait_timer)
393397
{
394398
status = NtCreateTimer (&wait_timer, TIMER_ALL_ACCESS, NULL,
@@ -431,6 +435,10 @@ next_while:;
431435
{
432436
BOOLEAN current_state;
433437
NtCancelTimer (wait_timer, &current_state);
438+
if (local_timer)
439+
NtClose (local_timer);
440+
else
441+
_my_tls.locals.cw_timer_inuse = false;
434442
}
435443

436444
wait_states res;

0 commit comments

Comments
 (0)