Skip to content

Commit 237213d

Browse files
committed
Merge branch 'xdebug_3_5'
* xdebug_3_5: Style fixes, and make log message type and text consistent Fixed issue #2395: Change Windows Named Pipe control socket implementation to use Overlapped I/O.
2 parents b234cd4 + 15bb848 commit 237213d

File tree

2 files changed

+92
-52
lines changed

2 files changed

+92
-52
lines changed

src/base/base_globals.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ typedef struct _xdebug_base_globals_t {
7272
# ifdef __linux__
7373
int control_socket_fd;
7474
# elif WIN32
75-
HANDLE control_socket_h;
75+
HANDLE control_socket_h;
76+
OVERLAPPED control_socket_ov;
7677
# endif
7778
#endif
7879

src/base/ctrl_socket.c

Lines changed: 90 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,9 @@ static void handle_command(HANDLE h, const char *line)
159159
#if __linux__
160160
write(fd, message->d, message->l);
161161
#elif WIN32
162-
WriteFile(
163-
h,
164-
message->d,
165-
message->l,
166-
NULL,
167-
NULL
168-
);
162+
if (WriteFile(h, message->d, message->l, NULL, &XG_BASE(control_socket_ov))) {
163+
SetEvent(XG_BASE(control_socket_ov).hEvent);
164+
}
169165
#endif
170166

171167
xdfree(cmd);
@@ -302,6 +298,32 @@ static void xdebug_control_socket_handle(void)
302298
}
303299
}
304300
#elif WIN32
301+
static bool named_pipe_listen()
302+
{
303+
if (ConnectNamedPipe(XG_BASE(control_socket_h), &XG_BASE(control_socket_ov))) {
304+
errno = GetLastError();
305+
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-HANDLE", "Can't create control Named Pipe Connect 1 (0x%x)", errno);
306+
return false;
307+
}
308+
309+
switch (GetLastError()) {
310+
case ERROR_IO_PENDING:
311+
break;
312+
case ERROR_PIPE_CONNECTED:
313+
if (!SetEvent(XG_BASE(control_socket_ov).hEvent)) {
314+
errno = GetLastError();
315+
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-HANDLE", "Can't create control Named Pipe Connect SetEvent (0x%x)", errno);
316+
return false;
317+
}
318+
default:
319+
errno = GetLastError();
320+
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-HANDLE", "Can't create control Named Pipe Connect 2 (0x%x)", errno);
321+
return false;
322+
}
323+
324+
return true;
325+
}
326+
305327
static void xdebug_control_socket_handle(void)
306328
{
307329
DWORD result;
@@ -313,56 +335,52 @@ static void xdebug_control_socket_handle(void)
313335
return;
314336
}
315337

316-
if (ConnectNamedPipe(XG_BASE(control_socket_h), NULL)) {
317-
/* Previous disconnect */
318-
DisconnectNamedPipe(XG_BASE(control_socket_h));
338+
if (WaitForSingleObject(XG_BASE(control_socket_ov).hEvent, 0) != WAIT_OBJECT_0) {
339+
/* No connection yet */
319340
return;
320341
}
321342

322-
result = GetLastError();
323-
324-
if (result == ERROR_PIPE_LISTENING) {
325-
/* No clients */
343+
if (!GetOverlappedResult(XG_BASE(control_socket_h), &XG_BASE(control_socket_ov), &bytes_read, TRUE)) {
344+
/* Error getting Overlapped result */
345+
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-HANDLE", "Can't receive from Named Pipe GetOverlappedResult 1 (0x%x)", GetLastError());
326346
return;
327347
}
328348

329-
if (result == ERROR_NO_DATA) {
330-
DisconnectNamedPipe(XG_BASE(control_socket_h));
331-
return;
332-
}
333-
334-
if (result == ERROR_PIPE_CONNECTED) {
335-
/* Got new client */
336-
DWORD lpMode;
337-
lpMode = PIPE_TYPE_BYTE | PIPE_WAIT;
338-
if (!SetNamedPipeHandleState(XG_BASE(control_socket_h), &lpMode, NULL, NULL)) {
339-
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-HANDLE", "Can't set NP handle state to 0x%x: 0x%x", lpMode, GetLastError());
340-
}
341-
342-
memset(buffer, 0, sizeof(buffer));
343-
bytes_read = 0;
344-
if (!ReadFile(
345-
XG_BASE(control_socket_h),
346-
buffer,
347-
sizeof(buffer),
348-
&bytes_read,
349-
NULL
350-
)) {
351-
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-HANDLE", "Can't receive from NP: 0x%x", GetLastError());
349+
memset(buffer, 0, sizeof(buffer));
350+
bytes_read = 0;
351+
if (!ReadFile(
352+
XG_BASE(control_socket_h),
353+
buffer,
354+
sizeof(buffer),
355+
&bytes_read,
356+
&XG_BASE(control_socket_ov)
357+
)) {
358+
errno = GetLastError();
359+
if (errno == ERROR_IO_PENDING) {
360+
WaitForSingleObject(XG_BASE(control_socket_ov).hEvent, INFINITY);
361+
/* Error? */
362+
if (!GetOverlappedResult(XG_BASE(control_socket_h), &XG_BASE(control_socket_ov), &bytes_read, TRUE)) {
363+
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-HANDLE", "Can't receive from Named Pipe GetOverlappedResult 2 (0x%x)", GetLastError());
364+
goto finish;
365+
}
352366
} else {
353-
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_INFO, "CTRL-HANDLE", "Received: '%s'", buffer);
354-
handle_command(XG_BASE(control_socket_h), buffer);
355-
FlushFileBuffers(XG_BASE(control_socket_h));
356-
}
357-
358-
lpMode = PIPE_TYPE_BYTE | PIPE_NOWAIT;
359-
if (!SetNamedPipeHandleState(XG_BASE(control_socket_h), &lpMode, NULL, NULL)) {
360-
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-HANDLE", "Can't (post)set NP handle state to 0x%x: 0x%x", lpMode, GetLastError());
367+
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-HANDLE", "Can't receive from Named Pipe (0x%x)", GetLastError());
368+
goto finish;
361369
}
362370
}
363371

364-
/* All other errors and completed reading should close the socket */
372+
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_INFO, "CTRL-HANDLE", "Received: '%s'", buffer);
373+
handle_command(XG_BASE(control_socket_h), buffer);
374+
WaitForSingleObject(XG_BASE(control_socket_ov).hEvent, INFINITY);
375+
GetOverlappedResult(XG_BASE(control_socket_h), &XG_BASE(control_socket_ov), &bytes_read, FALSE);
376+
377+
FlushFileBuffers(XG_BASE(control_socket_h));
378+
379+
finish:
365380
DisconnectNamedPipe(XG_BASE(control_socket_h));
381+
if (!named_pipe_listen()) {
382+
xdebug_control_socket_teardown();
383+
}
366384
}
367385
#endif
368386

@@ -482,11 +500,10 @@ void xdebug_control_socket_setup(void)
482500
XG_BASE(control_socket_path) = xdebug_sprintf("xdebug-ctrl." ZEND_ULONG_FMT, xdebug_get_pid());
483501
name = xdebug_sprintf("\\\\.\\pipe\\%s", XG_BASE(control_socket_path));
484502

485-
/* Part 1 – create Named Pipe */
486503
XG_BASE(control_socket_h) = CreateNamedPipeA(
487504
name,
488-
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
489-
PIPE_TYPE_BYTE | PIPE_NOWAIT | PIPE_REJECT_REMOTE_CLIENTS,
505+
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
506+
PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
490507
1,
491508
1024,
492509
1024,
@@ -495,11 +512,28 @@ void xdebug_control_socket_setup(void)
495512
);
496513

497514
if (XG_BASE(control_socket_h) == INVALID_HANDLE_VALUE) {
515+
XG_BASE(control_socket_h) = 0;
498516
errno = GetLastError();
499517
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-SOCKET", "Can't create control Named Pipe (0x%x)", errno);
500-
xdfree(XG_BASE(control_socket_path));
501-
XG_BASE(control_socket_path) = NULL;
518+
xdebug_control_socket_teardown();
519+
xdfree(name);
520+
return;
521+
}
522+
523+
XG_BASE(control_socket_ov).Offset = 0;
524+
XG_BASE(control_socket_ov).OffsetHigh = 0;
525+
XG_BASE(control_socket_ov).hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
502526

527+
if (XG_BASE(control_socket_ov).hEvent == NULL) {
528+
errno = GetLastError();
529+
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-SOCKET", "Can't create control Named Pipe Event (0x%x)", errno);
530+
xdebug_control_socket_teardown();
531+
xdfree(name);
532+
return;
533+
}
534+
535+
if (!named_pipe_listen()) {
536+
xdebug_control_socket_teardown();
503537
xdfree(name);
504538
return;
505539
}
@@ -516,8 +550,13 @@ void xdebug_control_socket_teardown(void)
516550
}
517551
if (XG_BASE(control_socket_h)) {
518552
DisconnectNamedPipe(XG_BASE(control_socket_h));
553+
CloseHandle(XG_BASE(control_socket_h));
519554
XG_BASE(control_socket_h) = 0;
520555
}
556+
if (XG_BASE(control_socket_ov).hEvent) {
557+
CloseHandle(XG_BASE(control_socket_ov).hEvent);
558+
XG_BASE(control_socket_ov).hEvent = 0;
559+
}
521560
}
522561
#endif
523562

0 commit comments

Comments
 (0)