win/signal.c
Go to the documentation of this file.
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2  * Permission is hereby granted, free of charge, to any person obtaining a copy
3  * of this software and associated documentation files (the "Software"), to
4  * deal in the Software without restriction, including without limitation the
5  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6  * sell copies of the Software, and to permit persons to whom the Software is
7  * furnished to do so, subject to the following conditions:
8  *
9  * The above copyright notice and this permission notice shall be included in
10  * all copies or substantial portions of the Software.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18  * IN THE SOFTWARE.
19  */
20 
21 #include <assert.h>
22 #include <signal.h>
23 
24 #include "uv.h"
25 #include "internal.h"
26 #include "handle-inl.h"
27 #include "req-inl.h"
28 
29 
30 RB_HEAD(uv_signal_tree_s, uv_signal_s);
31 
32 static struct uv_signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree);
33 static CRITICAL_SECTION uv__signal_lock;
34 
35 static BOOL WINAPI uv__signal_control_handler(DWORD type);
36 
39  int signum,
40  int oneshot);
41 
42 void uv_signals_init(void) {
43  InitializeCriticalSection(&uv__signal_lock);
44  if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE))
45  abort();
46 }
47 
48 
50  /* Compare signums first so all watchers with the same signnum end up
51  * adjacent. */
52  if (w1->signum < w2->signum) return -1;
53  if (w1->signum > w2->signum) return 1;
54 
55  /* Sort by loop pointer, so we can easily look up the first item after
56  * { .signum = x, .loop = NULL }. */
57  if ((uintptr_t) w1->loop < (uintptr_t) w2->loop) return -1;
58  if ((uintptr_t) w1->loop > (uintptr_t) w2->loop) return 1;
59 
60  if ((uintptr_t) w1 < (uintptr_t) w2) return -1;
61  if ((uintptr_t) w1 > (uintptr_t) w2) return 1;
62 
63  return 0;
64 }
65 
66 
67 RB_GENERATE_STATIC(uv_signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare)
68 
69 
70 /*
71  * Dispatches signal {signum} to all active uv_signal_t watchers in all loops.
72  * Returns 1 if the signal was dispatched to any watcher, or 0 if there were
73  * no active signal watchers observing this signal.
74  */
75 int uv__signal_dispatch(int signum) {
78  int dispatched;
79 
80  dispatched = 0;
81 
82  EnterCriticalSection(&uv__signal_lock);
83 
84  lookup.signum = signum;
85  lookup.loop = NULL;
86 
87  for (handle = RB_NFIND(uv_signal_tree_s, &uv__signal_tree, &lookup);
88  handle != NULL && handle->signum == signum;
89  handle = RB_NEXT(uv_signal_tree_s, &uv__signal_tree, handle)) {
90  unsigned long previous = InterlockedExchange(
91  (volatile LONG*) &handle->pending_signum, signum);
92 
94  continue;
95 
96  if (!previous) {
97  POST_COMPLETION_FOR_REQ(handle->loop, &handle->signal_req);
98  }
99 
100  dispatched = 1;
101  if (handle->flags & UV_SIGNAL_ONE_SHOT)
103  }
104 
105  LeaveCriticalSection(&uv__signal_lock);
106 
107  return dispatched;
108 }
109 
110 
111 static BOOL WINAPI uv__signal_control_handler(DWORD type) {
112  switch (type) {
113  case CTRL_C_EVENT:
114  return uv__signal_dispatch(SIGINT);
115 
116  case CTRL_BREAK_EVENT:
117  return uv__signal_dispatch(SIGBREAK);
118 
119  case CTRL_CLOSE_EVENT:
121  /* Windows will terminate the process after the control handler
122  * returns. After that it will just terminate our process. Therefore
123  * block the signal handler so the main loop has some time to pick up
124  * the signal and do something for a few seconds. */
125  Sleep(INFINITE);
126  return TRUE;
127  }
128  return FALSE;
129 
130  case CTRL_LOGOFF_EVENT:
131  case CTRL_SHUTDOWN_EVENT:
132  /* These signals are only sent to services. Services have their own
133  * notification mechanism, so there's no point in handling these. */
134 
135  default:
136  /* We don't handle these. */
137  return FALSE;
138  }
139 }
140 
141 
143  uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL);
144  handle->pending_signum = 0;
145  handle->signum = 0;
146  handle->signal_cb = NULL;
147 
148  UV_REQ_INIT(&handle->signal_req, UV_SIGNAL_REQ);
149  handle->signal_req.data = handle;
150 
151  return 0;
152 }
153 
154 
156  uv_signal_t* removed_handle;
157 
158  /* If the watcher wasn't started, this is a no-op. */
159  if (handle->signum == 0)
160  return 0;
161 
162  EnterCriticalSection(&uv__signal_lock);
163 
164  removed_handle = RB_REMOVE(uv_signal_tree_s, &uv__signal_tree, handle);
165  assert(removed_handle == handle);
166 
167  LeaveCriticalSection(&uv__signal_lock);
168 
169  handle->signum = 0;
171 
172  return 0;
173 }
174 
175 
177  return uv__signal_start(handle, signal_cb, signum, 0);
178 }
179 
180 
183  int signum) {
184  return uv__signal_start(handle, signal_cb, signum, 1);
185 }
186 
187 
190  int signum,
191  int oneshot) {
192  /* Test for invalid signal values. */
193  if (signum <= 0 || signum >= NSIG)
194  return UV_EINVAL;
195 
196  /* Short circuit: if the signal watcher is already watching {signum} don't go
197  * through the process of deregistering and registering the handler.
198  * Additionally, this avoids pending signals getting lost in the (small) time
199  * frame that handle->signum == 0. */
200  if (signum == handle->signum) {
201  handle->signal_cb = signal_cb;
202  return 0;
203  }
204 
205  /* If the signal handler was already active, stop it first. */
206  if (handle->signum != 0) {
207  int r = uv_signal_stop(handle);
208  /* uv_signal_stop is infallible. */
209  assert(r == 0);
210  }
211 
212  EnterCriticalSection(&uv__signal_lock);
213 
214  handle->signum = signum;
215  if (oneshot)
216  handle->flags |= UV_SIGNAL_ONE_SHOT;
217 
218  RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle);
219 
220  LeaveCriticalSection(&uv__signal_lock);
221 
222  handle->signal_cb = signal_cb;
224 
225  return 0;
226 }
227 
228 
230  uv_req_t* req) {
231  long dispatched_signum;
232 
233  assert(handle->type == UV_SIGNAL);
234  assert(req->type == UV_SIGNAL_REQ);
235 
236  dispatched_signum = InterlockedExchange(
237  (volatile LONG*) &handle->pending_signum, 0);
238  assert(dispatched_signum != 0);
239 
240  /* Check if the pending signal equals the signum that we are watching for.
241  * These can get out of sync when the handler is stopped and restarted while
242  * the signal_req is pending. */
243  if (dispatched_signum == handle->signum)
244  handle->signal_cb(handle, dispatched_signum);
245 
246  if (handle->flags & UV_SIGNAL_ONE_SHOT)
248 
249  if (handle->flags & UV_HANDLE_CLOSING) {
250  /* When it is closing, it must be stopped at this point. */
251  assert(handle->signum == 0);
253  }
254 }
255 
256 
260 
261  if (handle->pending_signum == 0) {
263  }
264 }
265 
266 
268  assert(handle->flags & UV_HANDLE_CLOSING);
269  assert(!(handle->flags & UV_HANDLE_CLOSED));
270 
271  assert(handle->signum == 0);
272  assert(handle->pending_signum == 0);
273 
274  handle->flags |= UV_HANDLE_CLOSED;
275 
277 }
TRUE
const BOOL TRUE
Definition: undname.c:48
async_greeter_server_with_graceful_shutdown.loop
loop
Definition: async_greeter_server_with_graceful_shutdown.py:59
UV_HANDLE_CLOSED
@ UV_HANDLE_CLOSED
Definition: uv-common.h:67
uv_process_signal_req
void uv_process_signal_req(uv_loop_t *loop, uv_signal_t *handle, uv_req_t *req)
Definition: win/signal.c:229
uv_signal_cb
void(* uv_signal_cb)(uv_signal_t *handle, int signum)
Definition: uv.h:376
RB_HEAD
RB_HEAD(uv_signal_tree_s, uv_signal_s)
RB_REMOVE
#define RB_REMOVE(name, x, y)
Definition: tree.h:728
generate_changelog.previous
previous
Definition: bloaty/third_party/protobuf/generate_changelog.py:55
SIGHUP
#define SIGHUP
Definition: win.h:86
POST_COMPLETION_FOR_REQ
#define POST_COMPLETION_FOR_REQ(loop, req)
Definition: req-inl.h:76
UV_SIGNAL_ONE_SHOT_DISPATCHED
@ UV_SIGNAL_ONE_SHOT_DISPATCHED
Definition: uv-common.h:120
uv__handle_close
#define uv__handle_close(handle)
Definition: handle-inl.h:76
uv_signal_stop
int uv_signal_stop(uv_signal_t *handle)
Definition: win/signal.c:155
uv_want_endgame
static INLINE void uv_want_endgame(uv_loop_t *loop, uv_handle_t *handle)
Definition: handle-inl.h:88
BOOL
int BOOL
Definition: undname.c:46
req-inl.h
uv__handle_closing
#define uv__handle_closing(handle)
Definition: handle-inl.h:63
uv_signal_endgame
void uv_signal_endgame(uv_loop_t *loop, uv_signal_t *handle)
Definition: win/signal.c:267
xds_interop_client.int
int
Definition: xds_interop_client.py:113
RB_NFIND
#define RB_NFIND(name, x, y)
Definition: tree.h:730
uv__signal_control_handler
static BOOL WINAPI uv__signal_control_handler(DWORD type)
Definition: win/signal.c:111
uv__signal_tree
static struct uv_signal_tree_s uv__signal_tree
Definition: win/signal.c:32
RB_NEXT
#define RB_NEXT(name, x, y)
Definition: tree.h:731
req
static uv_connect_t req
Definition: test-connection-fail.c:30
uv_signal_start_oneshot
int uv_signal_start_oneshot(uv_signal_t *handle, uv_signal_cb signal_cb, int signum)
Definition: win/signal.c:181
UV_SIGNAL_ONE_SHOT
@ UV_SIGNAL_ONE_SHOT
Definition: uv-common.h:121
uv_signals_init
void uv_signals_init(void)
Definition: win/signal.c:42
signal_cb
static void signal_cb(uv_signal_t *signal, int signum)
Definition: test-signal-pending-on-close.c:42
RB_INSERT
#define RB_INSERT(name, x, y)
Definition: tree.h:727
uv_signal_start
int uv_signal_start(uv_signal_t *handle, uv_signal_cb signal_cb, int signum)
Definition: win/signal.c:176
uintptr_t
_W64 unsigned int uintptr_t
Definition: stdint-msvc2008.h:119
uv__signal_lock
static CRITICAL_SECTION uv__signal_lock
Definition: win/signal.c:33
uv__handle_init
#define uv__handle_init(loop_, h, type_)
Definition: uv-common.h:284
uv.h
UV_REQ_INIT
#define UV_REQ_INIT(req, typ)
Definition: uv-common.h:305
UV_HANDLE_CLOSING
@ UV_HANDLE_CLOSING
Definition: uv-common.h:66
uv__signal_start
int uv__signal_start(uv_signal_t *handle, uv_signal_cb signal_cb, int signum, int oneshot)
Definition: win/signal.c:188
uv_signal_s
Definition: uv.h:1561
FALSE
const BOOL FALSE
Definition: undname.c:47
uv__signal_dispatch
int uv__signal_dispatch(int signum)
Definition: win/signal.c:75
uv_signal_close
void uv_signal_close(uv_loop_t *loop, uv_signal_t *handle)
Definition: win/signal.c:257
NSIG
#define NSIG
Definition: win.h:95
fix_build_deps.r
r
Definition: fix_build_deps.py:491
lookup
static bool lookup(const upb_table *t, lookupkey_t key, upb_value *v, uint32_t hash, eqlfunc_t *eql)
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/upb.c:1417
uv_signal_init
int uv_signal_init(uv_loop_t *loop, uv_signal_t *handle)
Definition: win/signal.c:142
uv_signal_s::signum
int signum
Definition: uv.h:1564
handle
static csh handle
Definition: test_arm_regression.c:16
uv_handle_s
Definition: uv.h:441
uv_loop_s
Definition: uv.h:1767
internal.h
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
uv__handle_start
#define uv__handle_start(h)
Definition: uv-common.h:241
handle-inl.h
uv__handle_stop
#define uv__handle_stop(h)
Definition: uv-common.h:249
RB_INITIALIZER
#define RB_INITIALIZER(root)
Definition: tree.h:301
RB_GENERATE_STATIC
RB_GENERATE_STATIC(uv__signal_tree_s, uv_signal_s, tree_entry, uv__signal_compare)
Definition: unix/signal.c:59
uv_req_s
Definition: uv.h:404
uv__signal_compare
static int uv__signal_compare(uv_signal_t *w1, uv_signal_t *w2)
Definition: win/signal.c:49


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:12