Skip to content

Commit 03a6d2f

Browse files
committed
fix(debugging): Do not close data socket prematurely
Multiple dispatch_io operations are usually running simultaneously. When recreating the inspector listening socket after an "AttachRequest" notification from {N} CLI, the following crash happened in a dispather worker thread: `BUG IN CLIENT OF LIBDISPATCH: Unexpected EV_VANISHED (do not destroy random mach ports or file descriptors)` The reason turned out that we always have at least 2 pending current operations. One is reading the next message, and the other one -- the cleanup handler from `dispatch_io_create`.
1 parent aa0e017 commit 03a6d2f

1 file changed

Lines changed: 25 additions & 9 deletions

File tree

src/debugging/TNSDebugging.h

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,18 +122,19 @@ TNSCreateInspectorServer(TNSInspectorFrontendConnectedHandler connectedHandler,
122122
__block dispatch_fd_t newSocket = accept(listenSocket, NULL, NULL);
123123

124124
__block dispatch_io_t io = 0;
125+
__block int dispatchOpsCount = 0;
126+
__block void (^decrementDispatchOpsCount)() = ^{
127+
if (--dispatchOpsCount <= 0) {
128+
if (newSocket != 0) {
129+
close(newSocket);
130+
newSocket = 0;
131+
}
132+
}
133+
};
125134
__block TNSInspectorProtocolHandler protocolHandler = nil;
126135
__block TNSInspectorIoErrorHandler dataSocketErrorHandler = ^(NSObject* dummy, NSError* error) {
127136
@synchronized(inspectorLock()) {
128-
if (io) {
129-
dispatch_io_close(io, DISPATCH_IO_STOP);
130-
io = 0;
131-
}
132-
}
133-
134-
if (newSocket) {
135-
close(newSocket);
136-
newSocket = 0;
137+
io = 0;
137138
}
138139

139140
if (protocolHandler) {
@@ -146,8 +147,10 @@ TNSCreateInspectorServer(TNSInspectorFrontendConnectedHandler connectedHandler,
146147
};
147148

148149
@synchronized(inspectorLock()) {
150+
++dispatchOpsCount;
149151
io = dispatch_io_create(DISPATCH_IO_STREAM, newSocket, queue,
150152
^(int error) {
153+
decrementDispatchOpsCount();
151154
CheckError(error, dataSocketErrorHandler);
152155
});
153156
}
@@ -175,8 +178,12 @@ TNSCreateInspectorServer(TNSInspectorFrontendConnectedHandler connectedHandler,
175178

176179
@synchronized(inspectorLock()) {
177180
if (io) {
181+
++dispatchOpsCount;
178182
dispatch_io_write(io, 0, data, queue,
179183
^(bool done, dispatch_data_t data, int error) {
184+
if (done) {
185+
decrementDispatchOpsCount();
186+
}
180187
CheckError(error, dataSocketErrorHandler);
181188
});
182189
}
@@ -190,6 +197,9 @@ TNSCreateInspectorServer(TNSInspectorFrontendConnectedHandler connectedHandler,
190197
}
191198

192199
__block dispatch_io_handler_t receiver = ^(bool done, dispatch_data_t data, int error) {
200+
if (done) {
201+
decrementDispatchOpsCount();
202+
}
193203
if (!CheckError(error, dataSocketErrorHandler)) {
194204
return;
195205
}
@@ -204,9 +214,13 @@ TNSCreateInspectorServer(TNSInspectorFrontendConnectedHandler connectedHandler,
204214
@synchronized(inspectorLock()) {
205215
if (io) {
206216
dispatch_io_set_low_water(io, length);
217+
++dispatchOpsCount;
207218
dispatch_io_read(
208219
io, 0, length, queue,
209220
^(bool done, dispatch_data_t data, int error) {
221+
if (done) {
222+
decrementDispatchOpsCount();
223+
}
210224
if (!CheckError(error, dataSocketErrorHandler)) {
211225
return;
212226
}
@@ -220,6 +234,7 @@ TNSCreateInspectorServer(TNSInspectorFrontendConnectedHandler connectedHandler,
220234
#pragma clang diagnostic ignored "-Warc-retain-cycles"
221235
@synchronized(inspectorLock()) {
222236
if (io) {
237+
++dispatchOpsCount;
223238
dispatch_io_read(io, 0, 4, queue, receiver);
224239
}
225240
}
@@ -231,6 +246,7 @@ TNSCreateInspectorServer(TNSInspectorFrontendConnectedHandler connectedHandler,
231246

232247
@synchronized(inspectorLock()) {
233248
if (io) {
249+
++dispatchOpsCount;
234250
dispatch_io_read(io, 0, 4, queue, receiver);
235251
}
236252
}

0 commit comments

Comments
 (0)