1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2014-2018 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