xref: /PHP-7.4/sapi/phpdbg/phpdbg_sigio_win32.c (revision c245898b)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) The PHP Group                                          |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Anatol Belski <ab@php.net>                                  |
16    +----------------------------------------------------------------------+
17 */
18 
19 
20 #include <signal.h>
21 
22 #include "phpdbg.h"
23 #include "phpdbg_sigio_win32.h"
24 
25 
ZEND_EXTERN_MODULE_GLOBALS(phpdbg)26 ZEND_EXTERN_MODULE_GLOBALS(phpdbg)
27 
28 
29 VOID
30 SigIoWatcherThread(VOID *p)
31 {
32 	zend_uchar sig;
33 	struct win32_sigio_watcher_data *swd = (struct win32_sigio_watcher_data *)p;
34 
35 top:
36 	(void)phpdbg_consume_bytes(swd->fd, &sig, 1, -1);
37 
38 
39 	if (3 == sig) {
40 		/* XXX completely not sure it is done right here */
41 		if (*swd->flags & PHPDBG_IS_INTERACTIVE) {
42 			if (raise(sig)) {
43 				goto top;
44 			}
45 		}
46 		if (*swd->flags & PHPDBG_IS_SIGNALED) {
47 			phpdbg_set_sigsafe_mem(&sig);
48 			zend_try {
49 				phpdbg_force_interruption();
50 			} zend_end_try();
51 			phpdbg_clear_sigsafe_mem();
52 			goto end;
53 		}
54 		if (!(*swd->flags & PHPDBG_IS_INTERACTIVE)) {
55 			*swd->flags |= PHPDBG_IS_SIGNALED;
56 		}
57 end:
58 		/* XXX set signaled flag to the caller thread, question is - whether it's needed */
59 		ExitThread(sig);
60 	} else {
61 		goto top;
62 	}
63 }
64 
65 
66 /* Start this only for the time of the run or eval command,
67 for so long that the main thread is busy serving some debug
68 session. */
69 void
sigio_watcher_start(void)70 sigio_watcher_start(void)
71 {
72 
73 	PHPDBG_G(swd).fd = PHPDBG_G(io)[PHPDBG_STDIN].fd;
74 #ifdef ZTS
75 	PHPDBG_G(swd).flags = &PHPDBG_G(flags);
76 #endif
77 
78 	PHPDBG_G(sigio_watcher_thread) = CreateThread(
79 		NULL,
80 		0,
81 		(LPTHREAD_START_ROUTINE)SigIoWatcherThread,
82 		&PHPDBG_G(swd),
83 		0,
84 		NULL);
85 }
86 
87 void
sigio_watcher_stop(void)88 sigio_watcher_stop(void)
89 {
90 	DWORD waited;
91 
92 	if (INVALID_HANDLE_VALUE == PHPDBG_G(sigio_watcher_thread)) {
93 		/* it probably did bail out already */
94 		return;
95 	}
96 
97 	waited = WaitForSingleObject(PHPDBG_G(sigio_watcher_thread), 300);
98 
99 	if (WAIT_OBJECT_0 != waited) {
100 		if (!CancelSynchronousIo(PHPDBG_G(sigio_watcher_thread))) {
101 			/* error out */
102 		}
103 
104 		if (!TerminateThread(PHPDBG_G(sigio_watcher_thread), 0)) {
105 			/* error out */
106 		}
107 	}
108 
109 	PHPDBG_G(swd).fd = -1;
110 	PHPDBG_G(sigio_watcher_thread) = INVALID_HANDLE_VALUE;
111 }
112