@@ -174,27 +174,62 @@ _dispatch_muxnote_create(dispatch_unote_t du,
174
174
}
175
175
176
176
static void
177
- _dispatch_muxnote_stop (dispatch_muxnote_t dmn )
177
+ _dispatch_muxnote_disarm_events (dispatch_muxnote_t dmn ,
178
+ enum _dispatch_muxnote_events events )
178
179
{
179
- if (dmn -> dmn_thread ) {
180
- // Keep trying to cancel ReadFile() until the thread exits
181
- os_atomic_store (& dmn -> dmn_stop , true, relaxed );
182
- SetEvent (dmn -> dmn_event );
183
- do {
184
- CancelIoEx ((HANDLE )dmn -> dmn_ident , /* lpOverlapped */ NULL );
185
- } while (WaitForSingleObject (dmn -> dmn_thread , 1 ) == WAIT_TIMEOUT );
186
- CloseHandle (dmn -> dmn_thread );
187
- dmn -> dmn_thread = NULL ;
188
- }
189
- if (dmn -> dmn_threadpool_wait ) {
190
- SetThreadpoolWait (dmn -> dmn_threadpool_wait , NULL , NULL );
191
- WaitForThreadpoolWaitCallbacks (dmn -> dmn_threadpool_wait ,
192
- /* fCancelPendingCallbacks */ FALSE);
193
- CloseThreadpoolWait (dmn -> dmn_threadpool_wait );
194
- dmn -> dmn_threadpool_wait = NULL ;
195
- }
196
- if (dmn -> dmn_handle_type == DISPATCH_MUXNOTE_HANDLE_TYPE_SOCKET ) {
197
- WSAEventSelect ((SOCKET )dmn -> dmn_ident , NULL , 0 );
180
+ long lNetworkEvents ;
181
+ dmn -> dmn_events &= ~events ;
182
+ switch (dmn -> dmn_handle_type ) {
183
+ case DISPATCH_MUXNOTE_HANDLE_TYPE_INVALID :
184
+ DISPATCH_INTERNAL_CRASH (0 , "invalid handle" );
185
+
186
+ case DISPATCH_MUXNOTE_HANDLE_TYPE_FILE :
187
+ break ;
188
+
189
+ case DISPATCH_MUXNOTE_HANDLE_TYPE_PIPE :
190
+ if ((events & DISPATCH_MUXNOTE_EVENT_READ ) && dmn -> dmn_thread ) {
191
+ // Keep trying to cancel ReadFile() until the thread exits
192
+ os_atomic_store (& dmn -> dmn_stop , true, relaxed );
193
+ SetEvent (dmn -> dmn_event );
194
+ do {
195
+ CancelIoEx ((HANDLE )dmn -> dmn_ident , /* lpOverlapped */ NULL );
196
+ } while (WaitForSingleObject (dmn -> dmn_thread , 1 ) == WAIT_TIMEOUT );
197
+ CloseHandle (dmn -> dmn_thread );
198
+ dmn -> dmn_thread = NULL ;
199
+ }
200
+ break ;
201
+
202
+ case DISPATCH_MUXNOTE_HANDLE_TYPE_SOCKET :
203
+ lNetworkEvents = dmn -> dmn_network_events ;
204
+ if (events & DISPATCH_MUXNOTE_EVENT_READ ) {
205
+ lNetworkEvents &= ~FD_READ ;
206
+ }
207
+ if (events & DISPATCH_MUXNOTE_EVENT_WRITE ) {
208
+ lNetworkEvents &= ~FD_WRITE ;
209
+ }
210
+ if (lNetworkEvents == dmn -> dmn_network_events ) {
211
+ break ;
212
+ }
213
+ int iResult ;
214
+ if (lNetworkEvents & (FD_READ | FD_WRITE )) {
215
+ iResult = WSAEventSelect ((SOCKET )dmn -> dmn_ident ,
216
+ (WSAEVENT )dmn -> dmn_event , lNetworkEvents );
217
+ } else {
218
+ lNetworkEvents = 0 ;
219
+ iResult = WSAEventSelect ((SOCKET )dmn -> dmn_ident , NULL , 0 );
220
+ }
221
+ if (iResult != 0 ) {
222
+ DISPATCH_INTERNAL_CRASH (WSAGetLastError (), "WSAEventSelect" );
223
+ }
224
+ dmn -> dmn_network_events = lNetworkEvents ;
225
+ if (!lNetworkEvents && dmn -> dmn_threadpool_wait ) {
226
+ SetThreadpoolWait (dmn -> dmn_threadpool_wait , NULL , NULL );
227
+ WaitForThreadpoolWaitCallbacks (dmn -> dmn_threadpool_wait ,
228
+ /* fCancelPendingCallbacks */ FALSE);
229
+ CloseThreadpoolWait (dmn -> dmn_threadpool_wait );
230
+ dmn -> dmn_threadpool_wait = NULL ;
231
+ }
232
+ break ;
198
233
}
199
234
}
200
235
@@ -389,8 +424,16 @@ _dispatch_io_trigger(dispatch_muxnote_t dmn)
389
424
}
390
425
if (dmn -> dmn_events & DISPATCH_MUXNOTE_EVENT_WRITE ) {
391
426
_dispatch_muxnote_retain (dmn );
392
- DWORD available =
427
+ DWORD available ;
428
+ if (dmn -> dmn_events & DISPATCH_MUXNOTE_EVENT_READ ) {
429
+ // We can't query a pipe which has a read source open on it
430
+ // because the ReadFile() in the background thread might cause
431
+ // NtQueryInformationFile() to block
432
+ available = 1 ;
433
+ } else {
434
+ available =
393
435
_dispatch_pipe_write_availability ((HANDLE )dmn -> dmn_ident );
436
+ }
394
437
bSuccess = PostQueuedCompletionStatus (hPort , available ,
395
438
(ULONG_PTR )DISPATCH_PORT_PIPE_HANDLE_WRITE ,
396
439
(LPOVERLAPPED )dmn );
@@ -487,8 +530,12 @@ _dispatch_unote_register_muxed(dispatch_unote_t du)
487
530
dmn = _dispatch_unote_muxnote_find (dmb , du ._du -> du_ident ,
488
531
du ._du -> du_filter );
489
532
if (dmn ) {
490
- WIN_PORT_ERROR ();
491
- DISPATCH_INTERNAL_CRASH (0 , "muxnote updating is not supported" );
533
+ if (events & ~dmn -> dmn_events ) {
534
+ dmn -> dmn_events |= events ;
535
+ if (_dispatch_io_trigger (dmn ) == FALSE) {
536
+ return false;
537
+ }
538
+ }
492
539
} else {
493
540
dmn = _dispatch_muxnote_create (du , events );
494
541
if (!dmn ) {
@@ -551,9 +598,18 @@ _dispatch_unote_unregister_muxed(dispatch_unote_t du)
551
598
}
552
599
dul -> du_muxnote = NULL ;
553
600
554
- LIST_REMOVE (dmn , dmn_list );
555
- _dispatch_muxnote_stop (dmn );
556
- _dispatch_muxnote_release (dmn );
601
+ enum _dispatch_muxnote_events disarmed = 0 ;
602
+ if (LIST_EMPTY (& dmn -> dmn_readers_head )) {
603
+ disarmed |= DISPATCH_MUXNOTE_EVENT_READ ;
604
+ }
605
+ if (LIST_EMPTY (& dmn -> dmn_writers_head )) {
606
+ disarmed |= DISPATCH_MUXNOTE_EVENT_WRITE ;
607
+ }
608
+ _dispatch_muxnote_disarm_events (dmn , disarmed );
609
+ if (!dmn -> dmn_events ) {
610
+ LIST_REMOVE (dmn , dmn_list );
611
+ _dispatch_muxnote_release (dmn );
612
+ }
557
613
558
614
_dispatch_unote_state_set (du , DU_STATE_UNREGISTERED );
559
615
return true;
0 commit comments