@@ -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+
305327static 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