Skip to content

Commit 79b951f

Browse files
committed
Merged pull request xdebug#1007
2 parents ac33f1a + 655f60a commit 79b951f

File tree

12 files changed

+231
-26
lines changed

12 files changed

+231
-26
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ tags
6464
.svn
6565
/*~
6666
/*.rej
67+
/x64
6768

6869
# Test files generated by `run-tests.php`
6970
*.diff

config.w32

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ ARG_WITH("xdebug", "Xdebug support", "no");
55
ARG_WITH("xdebug-compression", "whether to compress profiler files (requires zlib)", "no");
66

77
if (PHP_XDEBUG != 'no') {
8-
var XDEBUG_BASE_SOURCES="base.c filter.c"
8+
var XDEBUG_BASE_SOURCES="base.c filter.c ctrl_socket.c"
99
var XDEBUG_LIB_SOURCES="usefulstuff.c cmd_parser.c compat.c crc32.c file.c hash.c headers.c lib.c llist.c log.c set.c str.c timing.c var.c var_export_html.c var_export_line.c var_export_text.c var_export_xml.c xml.c"
1010

1111
var XDEBUG_COVERAGE_SOURCES="branch_info.c code_coverage.c"
@@ -54,5 +54,7 @@ if (PHP_XDEBUG != 'no') {
5454
}
5555
}
5656

57+
AC_DEFINE("HAVE_XDEBUG_CONTROL_SOCKET_SUPPORT", 1, "Xdebug control socket support");
58+
5759
AC_DEFINE("HAVE_XDEBUG", 1, "Xdebug support");
5860
}

src/base/base.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1323,10 +1323,14 @@ void xdebug_base_minit(INIT_FUNC_ARGS)
13231323

13241324
#if HAVE_XDEBUG_CONTROL_SOCKET_SUPPORT
13251325
XG_BASE(control_socket_path) = NULL;
1326+
# ifdef __linux__
13261327
XG_BASE(control_socket_fd) = 0;
13271328
XG_BASE(control_socket_last_trigger) = 0;
1329+
# elif WIN32
1330+
XG_BASE(control_socket_h) = 0;
1331+
XG_BASE(control_socket_last_trigger) = 0;
1332+
# endif
13281333
#endif
1329-
13301334
xdebug_base_overloaded_functions_setup();
13311335
}
13321336

@@ -1398,7 +1402,9 @@ void xdebug_base_rinit()
13981402
}
13991403
}
14001404
# endif
1405+
#endif
14011406

1407+
#if HAVE_XDEBUG_CONTROL_SOCKET_SUPPORT
14021408
if (XINI_BASE(control_socket_granularity) != XDEBUG_CONTROL_SOCKET_OFF) {
14031409
xdebug_control_socket_setup();
14041410
}

src/base/base_globals.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
+----------------------------------------------------------------------+
33
| Xdebug |
44
+----------------------------------------------------------------------+
5-
| Copyright (c) 2002-2024 Derick Rethans |
5+
| Copyright (c) 2002-2025 Derick Rethans |
66
+----------------------------------------------------------------------+
77
| This source file is subject to version 1.01 of the Xdebug license, |
88
| that is bundled with this package in the file LICENSE, and is |
@@ -21,7 +21,6 @@
2121
#include "lib/llist.h"
2222
#include "lib/vector.h"
2323

24-
2524
#if PHP_WIN32
2625
typedef void (WINAPI *WIN_PRECISE_TIME_FUNC)(LPFILETIME);
2726
#endif
@@ -68,8 +67,12 @@ typedef struct _xdebug_base_globals_t {
6867
#if HAVE_XDEBUG_CONTROL_SOCKET_SUPPORT
6968
/* Control Socket */
7069
char *control_socket_path;
71-
int control_socket_fd;
7270
zend_long control_socket_last_trigger;
71+
# ifdef __linux__
72+
int control_socket_fd;
73+
# elif WIN32
74+
HANDLE control_socket_h;
75+
# endif
7376
#endif
7477

7578
/* filters */

src/base/ctrl_socket.c

Lines changed: 145 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
+----------------------------------------------------------------------+
33
| Xdebug |
44
+----------------------------------------------------------------------+
5-
| Copyright (c) 2002-2024 Derick Rethans |
5+
| Copyright (c) 2002-2025 Derick Rethans |
66
+----------------------------------------------------------------------+
77
| This source file is subject to version 1.01 of the Xdebug license, |
88
| that is bundled with this package in the file LICENSE, and is |
@@ -14,6 +14,7 @@
1414
+----------------------------------------------------------------------+
1515
*/
1616

17+
#ifdef __linux__
1718
#include <stdio.h>
1819
#include <stdlib.h>
1920
#include <unistd.h>
@@ -23,6 +24,7 @@
2324
#include <signal.h>
2425
#include <string.h>
2526
#include <errno.h>
27+
#endif
2628

2729
#include "php_xdebug.h"
2830

@@ -33,6 +35,10 @@
3335
#include "lib/log.h"
3436
#include "lib/xml.h"
3537

38+
#if WIN32
39+
#include <windows.h>
40+
#endif
41+
3642
ZEND_EXTERN_MODULE_GLOBALS(xdebug)
3743

3844
typedef struct {
@@ -121,8 +127,11 @@ static xdebug_str *make_message(xdebug_xml_node *message)
121127
return ret;
122128
}
123129

124-
130+
#if __linux__
125131
static void handle_command(int fd, const char *line)
132+
#elif WIN32
133+
static void handle_command(HANDLE h, const char *line)
134+
#endif
126135
{
127136
char *cmd = NULL;
128137
xdebug_dbgp_arg *args;
@@ -147,7 +156,17 @@ static void handle_command(int fd, const char *line)
147156
}
148157

149158
message = make_message(retval);
159+
#if __linux__
150160
write(fd, message->d, message->l);
161+
#elif WIN32
162+
WriteFile(
163+
h,
164+
message->d,
165+
message->l,
166+
NULL,
167+
NULL
168+
);
169+
#endif
151170

152171
xdfree(cmd);
153172
xdebug_cmd_arg_dtor(args);
@@ -230,6 +249,7 @@ CTRL_FUNC(pause)
230249
xdebug_xml_add_child(*retval, response);
231250
}
232251

252+
#if __linux__
233253
static void xdebug_control_socket_handle(void)
234254
{
235255
char buffer[256];
@@ -281,10 +301,88 @@ static void xdebug_control_socket_handle(void)
281301
close(new_sd);
282302
}
283303
}
304+
#elif WIN32
305+
static void xdebug_control_socket_handle(void)
306+
{
307+
DWORD result;
308+
char buffer[256];
309+
int bytes_read;
284310

285-
void xdebug_control_socket_dispatch(void)
311+
if (XG_BASE(control_socket_h) <= 0) {
312+
// no NP
313+
return;
314+
}
315+
316+
if (ConnectNamedPipe(XG_BASE(control_socket_h), NULL)) {
317+
// previous disconnect
318+
DisconnectNamedPipe(XG_BASE(control_socket_h));
319+
return;
320+
}
321+
322+
result = GetLastError();
323+
324+
if (result == ERROR_PIPE_LISTENING) {
325+
// no clients
326+
return;
327+
}
328+
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_REJECT_REMOTE_CLIENTS;
338+
SetNamedPipeHandleState(XG_BASE(control_socket_h), &lpMode, NULL, NULL);
339+
340+
memset(buffer, 0, sizeof(buffer));
341+
bytes_read = 0;
342+
if (!ReadFile(
343+
XG_BASE(control_socket_h),
344+
buffer,
345+
sizeof(buffer),
346+
&bytes_read,
347+
NULL
348+
)) {
349+
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-RECV", "Can't receive from NP: %x", GetLastError());
350+
} else {
351+
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_INFO, "CTRL-RECV", "Received: '%s'", buffer);
352+
handle_command(0, buffer);
353+
FlushFileBuffers(XG_BASE(control_socket_h));
354+
}
355+
356+
lpMode = PIPE_TYPE_BYTE | PIPE_NOWAIT | PIPE_REJECT_REMOTE_CLIENTS;
357+
SetNamedPipeHandleState(XG_BASE(control_socket_h), &lpMode, NULL, NULL);
358+
}
359+
360+
// All other errors and completed reading should close the socket
361+
DisconnectNamedPipe(XG_BASE(control_socket_h));
362+
}
363+
#endif
364+
365+
#if __linux__
366+
static bool is_control_socket_active(void)
286367
{
287368
if (!XG_BASE(control_socket_path)) {
369+
return false;
370+
}
371+
return true;
372+
}
373+
#elif WIN32
374+
static bool is_control_socket_active(void)
375+
{
376+
if (XG_BASE(control_socket_h) <= 0) {
377+
return false;
378+
}
379+
return true;
380+
}
381+
#endif
382+
383+
void xdebug_control_socket_dispatch(void)
384+
{
385+
if (!is_control_socket_active()) {
288386
return;
289387
}
290388

@@ -304,6 +402,7 @@ void xdebug_control_socket_dispatch(void)
304402
xdebug_control_socket_handle();
305403
}
306404

405+
#ifdef __linux__
307406
void xdebug_control_socket_setup(void)
308407
{
309408
struct sockaddr_un *servaddr = NULL;
@@ -348,8 +447,7 @@ void xdebug_control_socket_setup(void)
348447
}
349448

350449
/* Part 3 — Listen */
351-
if (listen(XG_BASE(control_socket_fd), 32) < 0)
352-
{
450+
if (listen(XG_BASE(control_socket_fd), 32) < 0) {
353451
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-LISTEN", "Listen failed: %s", strerror(errno));
354452
xdfree(servaddr);
355453
xdfree(XG_BASE(control_socket_path));
@@ -370,5 +468,47 @@ void xdebug_control_socket_teardown(void)
370468
XG_BASE(control_socket_path) = NULL;
371469
}
372470
}
471+
#elif WIN32
472+
void xdebug_control_socket_setup(void)
473+
{
474+
XG_BASE(control_socket_last_trigger) = xdebug_get_nanotime();
475+
476+
XG_BASE(control_socket_path) = xdebug_sprintf("\\\\.\\pipe\\xdebug-ctrl." ZEND_ULONG_FMT, xdebug_get_pid());
477+
478+
/* Part 1 – create Named Pipe */
479+
XG_BASE(control_socket_h) = CreateNamedPipeA(
480+
XG_BASE(control_socket_path),
481+
PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE,
482+
PIPE_TYPE_BYTE | PIPE_NOWAIT | PIPE_REJECT_REMOTE_CLIENTS,
483+
1,
484+
1024,
485+
1024,
486+
0,
487+
NULL
488+
);
489+
490+
if (XG_BASE(control_socket_h) == INVALID_HANDLE_VALUE) {
491+
errno = WSAGetLastError();
492+
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_WARN, "CTRL-SOCKET", "Can't create control Named Pipe (%x)", errno);
493+
xdfree(XG_BASE(control_socket_path));
494+
XG_BASE(control_socket_path) = NULL;
495+
return;
496+
}
497+
498+
xdebug_log_ex(XLOG_CHAN_CONFIG, XLOG_INFO, "CTRL-OK", "Control socket set up successfully: '%s'", XG_BASE(control_socket_path));
499+
}
500+
501+
void xdebug_control_socket_teardown(void)
502+
{
503+
if (XG_BASE(control_socket_path)) {
504+
xdfree(XG_BASE(control_socket_path));
505+
XG_BASE(control_socket_path) = NULL;
506+
}
507+
if (XG_BASE(control_socket_h)) {
508+
DisconnectNamedPipe(XG_BASE(control_socket_h));
509+
XG_BASE(control_socket_h) = 0;
510+
}
511+
}
512+
#endif
373513

374514
#endif

src/lib/php-header.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
+----------------------------------------------------------------------+
33
| Xdebug |
44
+----------------------------------------------------------------------+
5-
| Copyright (c) 2002-2022 Derick Rethans |
5+
| Copyright (c) 2002-2025 Derick Rethans |
66
+----------------------------------------------------------------------+
77
| This source file is subject to version 1.01 of the Xdebug license, |
88
| that is bundled with this package in the file LICENSE, and is |
@@ -14,7 +14,11 @@
1414
+----------------------------------------------------------------------+
1515
*/
1616

17-
#pragma GCC diagnostic push
18-
#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
17+
#if !defined(_MSC_VER)
18+
# pragma GCC diagnostic push
19+
# pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
20+
#endif
1921
#include "php.h"
20-
#pragma GCC diagnostic pop
22+
#if !defined(_MSC_VER)
23+
# pragma GCC diagnostic pop
24+
#endif

src/lib/str.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020
#include <string.h>
2121
#include <locale.h>
2222

23-
#if PHP_VERSION_ID < 80200
23+
#if !defined(_MSC_VER)
2424
# pragma GCC diagnostic push
2525
# pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
26-
# include "zend_smart_str.h"
26+
#endif
27+
#include "zend_smart_str.h"
28+
#if !defined(_MSC_VER)
2729
# pragma GCC diagnostic pop
2830
#endif
2931

src/tracing/tracing.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
+----------------------------------------------------------------------+
33
| Xdebug |
44
+----------------------------------------------------------------------+
5-
| Copyright (c) 2002-2023 Derick Rethans |
5+
| Copyright (c) 2002-2025 Derick Rethans |
66
+----------------------------------------------------------------------+
77
| This source file is subject to version 1.01 of the Xdebug license, |
88
| that is bundled with this package in the file LICENSE, and is |
@@ -18,10 +18,14 @@
1818

1919
#include "lib/php-header.h"
2020

21-
#pragma GCC diagnostic push
22-
#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
21+
#if !defined(_MSC_VER)
22+
# pragma GCC diagnostic push
23+
# pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
24+
#endif
2325
#include "zend_generators.h"
24-
#pragma GCC diagnostic pop
26+
#if !defined(_MSC_VER)
27+
# pragma GCC diagnostic pop
28+
#endif
2529

2630
typedef struct
2731
{

tests/debugger/bug02261-001.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Test for bug #2261: Control socket in init package (Control Socket with TSC)
33
--SKIPIF--
44
<?php
55
require __DIR__ . '/../utils.inc';
6-
check_reqs('dbgp; ext-flag control-socket; ext-flag tsc');
6+
check_reqs('dbgp; ext-flag control-socket; ext-flag tsc; linux');
77
?>
88
--FILE--
99
<?php

0 commit comments

Comments
 (0)