]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/signal.cc
* cygwait.cc (cancelable_wait): Mimic old cygwait behavior more closely wrt
[newlib-cygwin.git] / winsup / cygwin / signal.cc
1 /* signal.cc
2
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 2005, 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
5
6 Written by Steve Chamberlain of Cygnus Support, sac@cygnus.com
7 Significant changes by Sergey Okhapkin <sos@prospect.com.ru>
8
9 This file is part of Cygwin.
10
11 This software is a copyrighted work licensed under the terms of the
12 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
13 details. */
14
15 #include "winsup.h"
16 #include <stdlib.h>
17 #include <sys/cygwin.h>
18 #include "pinfo.h"
19 #include "sigproc.h"
20 #include "cygtls.h"
21 #include "path.h"
22 #include "fhandler.h"
23 #include "dtable.h"
24 #include "cygheap.h"
25 #include "cygwait.h"
26
27 #define _SA_NORESTART 0x8000
28
29 static int sigaction_worker (int, const struct sigaction *, struct sigaction *, bool, const char *)
30 __attribute__ ((regparm (3)));
31
32 #define sigtrapped(func) ((func) != SIG_IGN && (func) != SIG_DFL)
33
34 extern "C" _sig_func_ptr
35 signal (int sig, _sig_func_ptr func)
36 {
37 sig_dispatch_pending ();
38 _sig_func_ptr prev;
39
40 /* check that sig is in right range */
41 if (sig < 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP)
42 {
43 set_errno (EINVAL);
44 syscall_printf ("SIG_ERR = signal (%d, %p)", sig, func);
45 return (_sig_func_ptr) SIG_ERR;
46 }
47
48 prev = global_sigs[sig].sa_handler;
49 struct sigaction& gs = global_sigs[sig];
50 if (gs.sa_flags & _SA_NORESTART)
51 gs.sa_flags &= ~SA_RESTART;
52 else
53 gs.sa_flags |= SA_RESTART;
54
55 gs.sa_mask = SIGTOMASK (sig);
56 gs.sa_handler = func;
57 gs.sa_flags &= ~SA_SIGINFO;
58
59 syscall_printf ("%p = signal (%d, %p)", prev, sig, func);
60 return prev;
61 }
62
63 extern "C" int
64 clock_nanosleep (clockid_t clk_id, int flags, const struct timespec *rqtp,
65 struct timespec *rmtp)
66 {
67 const bool abstime = (flags & TIMER_ABSTIME) ? true : false;
68 int res = 0;
69 sig_dispatch_pending ();
70 pthread_testcancel ();
71
72 if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec > 999999999L)
73 return EINVAL;
74
75 /* Explicitly disallowed by POSIX. Needs to be checked first to avoid
76 being caught by the following test. */
77 if (clk_id == CLOCK_THREAD_CPUTIME_ID)
78 return EINVAL;
79
80 /* support for CPU-time clocks is optional */
81 if (CLOCKID_IS_PROCESS (clk_id) || CLOCKID_IS_THREAD (clk_id))
82 return ENOTSUP;
83
84 switch (clk_id)
85 {
86 case CLOCK_REALTIME:
87 case CLOCK_MONOTONIC:
88 break;
89 default:
90 /* unknown or illegal clock ID */
91 return EINVAL;
92 }
93
94 LARGE_INTEGER timeout;
95
96 timeout.QuadPart = (LONGLONG) rqtp->tv_sec * NSPERSEC
97 + ((LONGLONG) rqtp->tv_nsec + 99LL) / 100LL;
98
99 if (abstime)
100 {
101 struct timespec tp;
102
103 clock_gettime (clk_id, &tp);
104 /* Check for immediate timeout */
105 if (tp.tv_sec > rqtp->tv_sec
106 || (tp.tv_sec == rqtp->tv_sec && tp.tv_nsec > rqtp->tv_nsec))
107 return 0;
108
109 if (clk_id == CLOCK_REALTIME)
110 timeout.QuadPart += FACTOR;
111 else
112 {
113 /* other clocks need to be handled with a relative timeout */
114 timeout.QuadPart -= tp.tv_sec * NSPERSEC + tp.tv_nsec / 100LL;
115 timeout.QuadPart *= -1LL;
116 }
117 }
118 else /* !abstime */
119 timeout.QuadPart *= -1LL;
120
121 syscall_printf ("clock_nanosleep (%ld.%09ld)", rqtp->tv_sec, rqtp->tv_nsec);
122
123 int rc = cancelable_wait (NULL, &timeout, cw_sig | cw_cancel | cw_cancel_self);
124 if (rc == WAIT_SIGNALED)
125 res = EINTR;
126
127 /* according to POSIX, rmtp is used only if !abstime */
128 if (rmtp && !abstime)
129 {
130 rmtp->tv_sec = (time_t) (timeout.QuadPart / NSPERSEC);
131 rmtp->tv_nsec = (long) ((timeout.QuadPart % NSPERSEC) * 100LL);
132 }
133
134 syscall_printf ("%d = clock_nanosleep(%lu, %d, %ld.%09ld, %ld.%09.ld)",
135 res, clk_id, flags, rqtp->tv_sec, rqtp->tv_nsec,
136 rmtp ? rmtp->tv_sec : 0, rmtp ? rmtp->tv_nsec : 0);
137 return res;
138 }
139
140 extern "C" int
141 nanosleep (const struct timespec *rqtp, struct timespec *rmtp)
142 {
143 int res = clock_nanosleep (CLOCK_REALTIME, 0, rqtp, rmtp);
144 if (res != 0)
145 {
146 set_errno (res);
147 return -1;
148 }
149 return 0;
150 }
151
152 extern "C" unsigned int
153 sleep (unsigned int seconds)
154 {
155 struct timespec req, rem;
156 req.tv_sec = seconds;
157 req.tv_nsec = 0;
158 if (clock_nanosleep (CLOCK_REALTIME, 0, &req, &rem))
159 return rem.tv_sec + (rem.tv_nsec > 0);
160 return 0;
161 }
162
163 extern "C" unsigned int
164 usleep (useconds_t useconds)
165 {
166 struct timespec req;
167 req.tv_sec = useconds / 1000000;
168 req.tv_nsec = (useconds % 1000000) * 1000;
169 int res = clock_nanosleep (CLOCK_REALTIME, 0, &req, NULL);
170 if (res != 0)
171 {
172 set_errno (res);
173 return -1;
174 }
175 return 0;
176 }
177
178 extern "C" int
179 sigprocmask (int how, const sigset_t *set, sigset_t *oldset)
180 {
181 int res = handle_sigprocmask (how, set, oldset, _my_tls.sigmask);
182 if (res)
183 {
184 set_errno (res);
185 res = -1;
186 }
187 syscall_printf ("%R = sigprocmask (%d, %p, %p)", res, set, oldset);
188 return res;
189 }
190
191 int __stdcall
192 handle_sigprocmask (int how, const sigset_t *set, sigset_t *oldset, sigset_t& opmask)
193 {
194 /* check that how is in right range */
195 if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK)
196 {
197 syscall_printf ("Invalid how value %d", how);
198 return EINVAL;
199 }
200
201 myfault efault;
202 if (efault.faulted (EFAULT))
203 return EFAULT;
204
205 if (oldset)
206 *oldset = opmask;
207
208 if (set)
209 {
210 sigset_t newmask = opmask;
211 switch (how)
212 {
213 case SIG_BLOCK:
214 /* add set to current mask */
215 newmask |= *set;
216 break;
217 case SIG_UNBLOCK:
218 /* remove set from current mask */
219 newmask &= ~*set;
220 break;
221 case SIG_SETMASK:
222 /* just set it */
223 newmask = *set;
224 break;
225 }
226 set_signal_mask (newmask, opmask);
227 }
228 return 0;
229 }
230
231 int __stdcall
232 _pinfo::kill (siginfo_t& si)
233 {
234 int res;
235 DWORD this_process_state;
236 pid_t this_pid;
237
238 sig_dispatch_pending ();
239
240 if (exists ())
241 {
242 bool sendSIGCONT;
243 this_process_state = process_state;
244 if ((sendSIGCONT = (si.si_signo < 0)))
245 si.si_signo = -si.si_signo;
246
247 if (si.si_signo == 0)
248 res = 0;
249 else if ((res = sig_send (this, si)))
250 {
251 sigproc_printf ("%d = sig_send, %E ", res);
252 res = -1;
253 }
254 else if (sendSIGCONT)
255 {
256 siginfo_t si2 = {0};
257 si2.si_signo = SIGCONT;
258 si2.si_code = SI_KERNEL;
259 sig_send (this, si2);
260 }
261 this_pid = pid;
262 }
263 else if (si.si_signo == 0 && this && process_state == PID_EXITED)
264 {
265 this_process_state = process_state;
266 this_pid = pid;
267 res = 0;
268 }
269 else
270 {
271 set_errno (ESRCH);
272 this_process_state = 0;
273 this_pid = 0;
274 res = -1;
275 }
276
277 syscall_printf ("%d = _pinfo::kill (%d), pid %d, process_state %p", res,
278 si.si_signo, this_pid, this_process_state);
279 return res;
280 }
281
282 int
283 raise (int sig)
284 {
285 return kill (myself->pid, sig);
286 }
287
288 static int
289 kill0 (pid_t pid, siginfo_t& si)
290 {
291 syscall_printf ("kill (%d, %d)", pid, si.si_signo);
292 /* check that sig is in right range */
293 if (si.si_signo < 0 || si.si_signo >= NSIG)
294 {
295 set_errno (EINVAL);
296 syscall_printf ("signal %d out of range", si.si_signo);
297 return -1;
298 }
299
300 return (pid > 0) ? pinfo (pid)->kill (si) : kill_pgrp (-pid, si);
301 }
302
303 int
304 killsys (pid_t pid, int sig)
305 {
306 siginfo_t si = {0};
307 si.si_signo = sig;
308 si.si_code = SI_KERNEL;
309 return kill0 (pid, si);
310 }
311
312 int
313 kill (pid_t pid, int sig)
314 {
315 siginfo_t si = {0};
316 si.si_signo = sig;
317 si.si_code = SI_USER;
318 return kill0 (pid, si);
319 }
320
321 int
322 kill_pgrp (pid_t pid, siginfo_t& si)
323 {
324 int res = 0;
325 int found = 0;
326 int killself = 0;
327
328 sigproc_printf ("pid %d, signal %d", pid, si.si_signo);
329
330 winpids pids ((DWORD) PID_MAP_RW);
331 for (unsigned i = 0; i < pids.npids; i++)
332 {
333 _pinfo *p = pids[i];
334
335 if (!p->exists ())
336 continue;
337
338 /* Is it a process we want to kill? */
339 if ((pid == 0 && (p->pgid != myself->pgid || p->ctty != myself->ctty)) ||
340 (pid > 1 && p->pgid != pid) ||
341 (si.si_signo < 0 && NOTSTATE (p, PID_STOPPED)))
342 continue;
343 sigproc_printf ("killing pid %d, pgrp %d, p->%s, %s", p->pid, p->pgid,
344 p->__ctty (), myctty ());
345 if (p == myself)
346 killself++;
347 else if (p->kill (si))
348 res = -1;
349 found++;
350 }
351
352 if (killself && !exit_state && myself->kill (si))
353 res = -1;
354
355 if (!found)
356 {
357 set_errno (ESRCH);
358 res = -1;
359 }
360 syscall_printf ("%R = kill(%d, %d)", res, pid, si.si_signo);
361 return res;
362 }
363
364 extern "C" int
365 killpg (pid_t pgrp, int sig)
366 {
367 return kill (-pgrp, sig);
368 }
369
370 extern "C" void
371 abort (void)
372 {
373 _my_tls.incyg++;
374 sig_dispatch_pending ();
375 /* Ensure that SIGABRT can be caught regardless of blockage. */
376 sigset_t sig_mask;
377 sigfillset (&sig_mask);
378 sigdelset (&sig_mask, SIGABRT);
379 set_signal_mask (sig_mask, _my_tls.sigmask);
380
381 raise (SIGABRT);
382 _my_tls.call_signal_handler (); /* Call any signal handler */
383
384 /* Flush all streams as per SUSv2. */
385 if (_GLOBAL_REENT->__cleanup)
386 _GLOBAL_REENT->__cleanup (_GLOBAL_REENT);
387 do_exit (SIGABRT); /* signal handler didn't exit. Goodbye. */
388 }
389
390 static int
391 sigaction_worker (int sig, const struct sigaction *newact,
392 struct sigaction *oldact, bool isinternal, const char *fnname)
393 {
394 int res = -1;
395 myfault efault;
396 if (!efault.faulted (EFAULT))
397 {
398 sig_dispatch_pending ();
399 /* check that sig is in right range */
400 if (sig < 0 || sig >= NSIG)
401 set_errno (EINVAL);
402 else
403 {
404 struct sigaction oa = global_sigs[sig];
405
406 if (!newact)
407 sigproc_printf ("signal %d, newact %p, oa %p", sig, newact, oa, oa.sa_handler);
408 else
409 {
410 sigproc_printf ("signal %d, newact %p (handler %p), oa %p", sig, newact, newact->sa_handler, oa, oa.sa_handler);
411 if (sig == SIGKILL || sig == SIGSTOP)
412 {
413 set_errno (EINVAL);
414 goto out;
415 }
416 struct sigaction na = *newact;
417 struct sigaction& gs = global_sigs[sig];
418 if (!isinternal)
419 na.sa_flags &= ~_SA_INTERNAL_MASK;
420 gs = na;
421 if (!(gs.sa_flags & SA_NODEFER))
422 gs.sa_mask |= SIGTOMASK(sig);
423 if (gs.sa_handler == SIG_IGN)
424 sig_clear (sig);
425 if (gs.sa_handler == SIG_DFL && sig == SIGCHLD)
426 sig_clear (sig);
427 if (sig == SIGCHLD)
428 {
429 myself->process_state &= ~PID_NOCLDSTOP;
430 if (gs.sa_flags & SA_NOCLDSTOP)
431 myself->process_state |= PID_NOCLDSTOP;
432 }
433 }
434
435 if (oldact)
436 {
437 *oldact = oa;
438 oa.sa_flags &= ~_SA_INTERNAL_MASK;
439 }
440 res = 0;
441 }
442 }
443
444 out:
445 syscall_printf ("%R = %s(%d, %p, %p)", res, fnname, sig, newact, oldact);
446 return res;
447 }
448
449 extern "C" int
450 sigaction (int sig, const struct sigaction *newact, struct sigaction *oldact)
451 {
452 return sigaction_worker (sig, newact, oldact, false, "sigaction");
453 }
454
455 extern "C" int
456 sigaddset (sigset_t *set, const int sig)
457 {
458 /* check that sig is in right range */
459 if (sig <= 0 || sig >= NSIG)
460 {
461 set_errno (EINVAL);
462 syscall_printf ("SIG_ERR = sigaddset signal %d out of range", sig);
463 return -1;
464 }
465
466 *set |= SIGTOMASK (sig);
467 return 0;
468 }
469
470 extern "C" int
471 sigdelset (sigset_t *set, const int sig)
472 {
473 /* check that sig is in right range */
474 if (sig <= 0 || sig >= NSIG)
475 {
476 set_errno (EINVAL);
477 syscall_printf ("SIG_ERR = sigdelset signal %d out of range", sig);
478 return -1;
479 }
480
481 *set &= ~SIGTOMASK (sig);
482 return 0;
483 }
484
485 extern "C" int
486 sigismember (const sigset_t *set, int sig)
487 {
488 /* check that sig is in right range */
489 if (sig <= 0 || sig >= NSIG)
490 {
491 set_errno (EINVAL);
492 syscall_printf ("SIG_ERR = sigdelset signal %d out of range", sig);
493 return -1;
494 }
495
496 if (*set & SIGTOMASK (sig))
497 return 1;
498 else
499 return 0;
500 }
501
502 extern "C" int
503 sigemptyset (sigset_t *set)
504 {
505 *set = (sigset_t) 0;
506 return 0;
507 }
508
509 extern "C" int
510 sigfillset (sigset_t *set)
511 {
512 *set = ~((sigset_t) 0);
513 return 0;
514 }
515
516 extern "C" int
517 sigsuspend (const sigset_t *set)
518 {
519 return handle_sigsuspend (*set);
520 }
521
522 extern "C" int
523 sigpause (int signal_mask)
524 {
525 return handle_sigsuspend ((sigset_t) signal_mask);
526 }
527
528 extern "C" int
529 pause (void)
530 {
531 return handle_sigsuspend (_my_tls.sigmask);
532 }
533
534 extern "C" int
535 siginterrupt (int sig, int flag)
536 {
537 struct sigaction act;
538 sigaction (sig, NULL, &act);
539 if (flag)
540 {
541 act.sa_flags &= ~SA_RESTART;
542 act.sa_flags |= _SA_NORESTART;
543 }
544 else
545 {
546 act.sa_flags &= ~_SA_NORESTART;
547 act.sa_flags |= SA_RESTART;
548 }
549 return sigaction_worker (sig, &act, NULL, true, "siginterrupt");
550 }
551
552 extern "C" int
553 sigwait (const sigset_t *set, int *sig_ptr)
554 {
555 int sig = sigwaitinfo (set, NULL);
556 if (sig > 0)
557 *sig_ptr = sig;
558 return sig > 0 ? 0 : -1;
559 }
560
561 extern "C" int
562 sigwaitinfo (const sigset_t *set, siginfo_t *info)
563 {
564 pthread_testcancel ();
565
566 _my_tls.sigwait_mask = *set;
567 sig_dispatch_pending (true);
568
569 int res;
570 switch (cancelable_wait (NULL, NULL, cw_sig | cw_cancel | cw_cancel_self))
571 {
572 case WAIT_SIGNALED:
573 if (!sigismember (set, _my_tls.infodata.si_signo))
574 {
575 set_errno (EINTR);
576 res = -1;
577 }
578 else
579 {
580 if (info)
581 *info = _my_tls.infodata;
582 res = _my_tls.infodata.si_signo;
583 InterlockedExchange ((LONG *) &_my_tls.sig, (LONG) 0);
584 }
585 break;
586 default:
587 __seterrno ();
588 res = -1;
589 }
590
591 sigproc_printf ("returning signal %d", res);
592 return res;
593 }
594
595 /* FIXME: SUSv3 says that this function should block until the signal has
596 actually been delivered. Currently, this will only happen when sending
597 signals to the current process. It will not happen when sending signals
598 to other processes. */
599 extern "C" int
600 sigqueue (pid_t pid, int sig, const union sigval value)
601 {
602 siginfo_t si = {0};
603 pinfo dest (pid);
604 if (!dest)
605 {
606 set_errno (ESRCH);
607 return -1;
608 }
609 si.si_signo = sig;
610 si.si_code = SI_QUEUE;
611 si.si_value = value;
612 return sig_send (dest, si);
613 }
This page took 0.061849 seconds and 5 git commands to generate.