@@ -225,77 +225,19 @@ pg_queue_signal(int signum)
225
225
SetEvent (pgwin32_signal_event );
226
226
}
227
227
228
- /*
229
- * Signal dispatching thread. This runs after we have received a named
230
- * pipe connection from a client (signal sender). Process the request,
231
- * close the pipe, and exit.
232
- */
233
- static DWORD WINAPI
234
- pg_signal_dispatch_thread (LPVOID param )
235
- {
236
- HANDLE pipe = (HANDLE ) param ;
237
- BYTE sigNum ;
238
- DWORD bytes ;
239
-
240
- if (!ReadFile (pipe , & sigNum , 1 , & bytes , NULL ))
241
- {
242
- /* Client died before sending */
243
- CloseHandle (pipe );
244
- return 0 ;
245
- }
246
- if (bytes != 1 )
247
- {
248
- /* Received <bytes> bytes over signal pipe (should be 1) */
249
- CloseHandle (pipe );
250
- return 0 ;
251
- }
252
-
253
- /*
254
- * Queue the signal before responding to the client. In this way, it's
255
- * guaranteed that once kill() has returned in the signal sender, the next
256
- * CHECK_FOR_INTERRUPTS() in the signal recipient will see the signal.
257
- * (This is a stronger guarantee than POSIX makes; maybe we don't need it?
258
- * But without it, we've seen timing bugs on Windows that do not manifest
259
- * on any known Unix.)
260
- */
261
- pg_queue_signal (sigNum );
262
-
263
- /*
264
- * Write something back to the client, allowing its CallNamedPipe() call
265
- * to terminate.
266
- */
267
- WriteFile (pipe , & sigNum , 1 , & bytes , NULL ); /* Don't care if it works or
268
- * not.. */
269
-
270
- /*
271
- * We must wait for the client to read the data before we can close the
272
- * pipe, else the data will be lost. (If the WriteFile call failed,
273
- * there'll be nothing in the buffer, so this shouldn't block.)
274
- */
275
- FlushFileBuffers (pipe );
276
-
277
- /* This is a formality, since we're about to close the pipe anyway. */
278
- DisconnectNamedPipe (pipe );
279
-
280
- /* And we're done. */
281
- CloseHandle (pipe );
282
-
283
- return 0 ;
284
- }
285
-
286
228
/* Signal handling thread */
287
229
static DWORD WINAPI
288
230
pg_signal_thread (LPVOID param )
289
231
{
290
232
char pipename [128 ];
291
233
HANDLE pipe = pgwin32_initial_signal_pipe ;
292
234
235
+ /* Set up pipe name, in case we have to re-create the pipe. */
293
236
snprintf (pipename , sizeof (pipename ), "\\\\.\\pipe\\pgsignal_%lu" , GetCurrentProcessId ());
294
237
295
238
for (;;)
296
239
{
297
240
BOOL fConnected ;
298
- HANDLE hThread ;
299
241
300
242
/* Create a new pipe instance if we don't have one. */
301
243
if (pipe == INVALID_HANDLE_VALUE )
@@ -320,59 +262,62 @@ pg_signal_thread(LPVOID param)
320
262
fConnected = ConnectNamedPipe (pipe , NULL ) ? TRUE : (GetLastError () == ERROR_PIPE_CONNECTED );
321
263
if (fConnected )
322
264
{
323
- HANDLE newpipe ;
324
-
325
265
/*
326
- * We have a connected pipe. Pass this off to a separate thread
327
- * that will do the actual processing of the pipe.
328
- *
329
- * We must also create a new instance of the pipe *before* we
330
- * start running the new thread. If we don't, there is a race
331
- * condition whereby the dispatch thread might run CloseHandle()
332
- * before we have created a new instance, thereby causing a small
333
- * window of time where we will miss incoming requests.
266
+ * We have a connection from a would-be signal sender. Process it.
334
267
*/
335
- newpipe = CreateNamedPipe (pipename , PIPE_ACCESS_DUPLEX ,
336
- PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT ,
337
- PIPE_UNLIMITED_INSTANCES , 16 , 16 , 1000 , NULL );
338
- if (newpipe == INVALID_HANDLE_VALUE )
268
+ BYTE sigNum ;
269
+ DWORD bytes ;
270
+
271
+ if (ReadFile (pipe , & sigNum , 1 , & bytes , NULL ) &&
272
+ bytes == 1 )
339
273
{
340
274
/*
341
- * This really should never fail. Just retry in case it does,
342
- * even though we have a small race window in that case. There
343
- * is nothing else we can do other than abort the whole
344
- * process which will be even worse.
275
+ * Queue the signal before responding to the client. In this
276
+ * way, it's guaranteed that once kill() has returned in the
277
+ * signal sender, the next CHECK_FOR_INTERRUPTS() in the
278
+ * signal recipient will see the signal. (This is a stronger
279
+ * guarantee than POSIX makes; maybe we don't need it? But
280
+ * without it, we've seen timing bugs on Windows that do not
281
+ * manifest on any known Unix.)
345
282
*/
346
- write_stderr ( "could not create signal listener pipe: error code %lu; retrying\n" , GetLastError () );
283
+ pg_queue_signal ( sigNum );
347
284
348
285
/*
349
- * Keep going so we at least dispatch this signal. Hopefully,
350
- * the call will succeed when retried in the loop soon after .
286
+ * Write something back to the client, allowing its
287
+ * CallNamedPipe() call to terminate .
351
288
*/
289
+ WriteFile (pipe , & sigNum , 1 , & bytes , NULL ); /* Don't care if it
290
+ * works or not */
291
+
292
+ /*
293
+ * We must wait for the client to read the data before we can
294
+ * disconnect, else the data will be lost. (If the WriteFile
295
+ * call failed, there'll be nothing in the buffer, so this
296
+ * shouldn't block.)
297
+ */
298
+ FlushFileBuffers (pipe );
352
299
}
353
- hThread = CreateThread (NULL , 0 ,
354
- (LPTHREAD_START_ROUTINE ) pg_signal_dispatch_thread ,
355
- (LPVOID ) pipe , 0 , NULL );
356
- if (hThread == INVALID_HANDLE_VALUE )
357
- write_stderr ("could not create signal dispatch thread: error code %lu\n" ,
358
- GetLastError ());
359
300
else
360
- CloseHandle (hThread );
301
+ {
302
+ /*
303
+ * If we fail to read a byte from the client, assume it's the
304
+ * client's problem and do nothing. Perhaps it'd be better to
305
+ * force a pipe close and reopen?
306
+ */
307
+ }
361
308
362
- /*
363
- * Background thread is running with our instance of the pipe. So
364
- * replace our reference with the newly created one and loop back
365
- * up for another run.
366
- */
367
- pipe = newpipe ;
309
+ /* Disconnect from client so that we can re-use the pipe. */
310
+ DisconnectNamedPipe (pipe );
368
311
}
369
312
else
370
313
{
371
314
/*
372
- * Connection failed. Cleanup and try again.
315
+ * Connection failed. Cleanup and try again.
373
316
*
374
- * This should never happen. If it does, we have a small race
375
- * condition until we loop up and re-create the pipe.
317
+ * This should never happen. If it does, there's a window where
318
+ * we'll miss signals until we manage to re-create the pipe.
319
+ * However, just trying to use the same pipe again is probably not
320
+ * going to work, so we have little choice.
376
321
*/
377
322
CloseHandle (pipe );
378
323
pipe = INVALID_HANDLE_VALUE ;
0 commit comments