Cygwin: pinfo: use stpcpy where appropriate
[newlib-cygwin.git] / winsup / cygwin / signal.cc
blob77152910b583591a1ad4bb8e3e35d50541928ee5
1 /* signal.cc
3 Written by Steve Chamberlain of Cygnus Support, sac@cygnus.com
4 Significant changes by Sergey Okhapkin <sos@prospect.com.ru>
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10 details. */
12 #include "winsup.h"
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <sys/cygwin.h>
16 #include <sys/signalfd.h>
17 #include <sys/reent.h> /* needed for __stdio_exit_handler declaration */
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 #include "posix_timer.h"
28 #define _SA_NORESTART 0x8000
30 static int sigaction_worker (int, const struct sigaction *, struct sigaction *, bool);
32 #define sigtrapped(func) ((func) != SIG_IGN && (func) != SIG_DFL)
34 extern "C" _sig_func_ptr
35 signal (int sig, _sig_func_ptr func)
37 sig_dispatch_pending ();
38 _sig_func_ptr prev;
40 /* check that sig is in right range */
41 if (sig <= 0 || sig >= _NSIG || sig == SIGKILL || sig == SIGSTOP)
43 set_errno (EINVAL);
44 syscall_printf ("SIG_ERR = signal (%d, %p)", sig, func);
45 return (_sig_func_ptr) SIG_ERR;
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;
55 gs.sa_mask = SIGTOMASK (sig);
56 gs.sa_handler = func;
57 gs.sa_flags &= ~SA_SIGINFO;
59 syscall_printf ("%p = signal (%d, %p)", prev, sig, func);
60 return prev;
63 extern "C" int
64 clock_nanosleep (clockid_t clk_id, int flags, const struct timespec *rqtp,
65 struct timespec *rmtp)
67 const bool abstime = (flags & TIMER_ABSTIME) ? true : false;
68 int res = 0;
69 sig_dispatch_pending ();
70 pthread_testcancel ();
72 __try
74 if (!valid_timespec (*rqtp))
75 return EINVAL;
77 __except (NO_ERROR)
79 return EFAULT;
81 __endtry
83 /* Explicitly disallowed by POSIX. Needs to be checked first to avoid
84 being caught by the following test. */
85 if (clk_id == CLOCK_THREAD_CPUTIME_ID)
86 return EINVAL;
88 /* support for CPU-time clocks is optional */
89 if (CLOCKID_IS_PROCESS (clk_id) || CLOCKID_IS_THREAD (clk_id))
90 return ENOTSUP;
91 /* All other valid clocks are valid */
92 if (clk_id >= MAX_CLOCKS)
93 return EINVAL;
95 LARGE_INTEGER timeout;
97 timeout.QuadPart = (LONGLONG) rqtp->tv_sec * NS100PERSEC
98 + ((LONGLONG) rqtp->tv_nsec + (NSPERSEC/NS100PERSEC) - 1)
99 / (NSPERSEC/NS100PERSEC);
101 if (abstime)
103 struct timespec tp;
105 clock_gettime (clk_id, &tp);
106 /* Check for immediate timeout */
107 if (tp.tv_sec > rqtp->tv_sec
108 || (tp.tv_sec == rqtp->tv_sec && tp.tv_nsec > rqtp->tv_nsec))
109 return 0;
111 switch (clk_id)
113 case CLOCK_REALTIME_COARSE:
114 case CLOCK_REALTIME:
115 timeout.QuadPart += FACTOR;
116 break;
117 default:
118 /* other clocks need to be handled with a relative timeout */
119 timeout.QuadPart -= tp.tv_sec * NS100PERSEC
120 + tp.tv_nsec / (NSPERSEC/NS100PERSEC);
121 timeout.QuadPart *= -1LL;
122 break;
125 else /* !abstime */
126 timeout.QuadPart *= -1LL;
128 syscall_printf ("clock_nanosleep (%ld.%09ld)", rqtp->tv_sec, rqtp->tv_nsec);
130 int rc = cygwait (NULL, &timeout, cw_sig_eintr | cw_cancel | cw_cancel_self);
131 if (rc == WAIT_SIGNALED)
132 res = EINTR;
134 /* according to POSIX, rmtp is used only if !abstime */
135 if (rmtp && !abstime)
137 __try
139 rmtp->tv_sec = (time_t) (timeout.QuadPart / NS100PERSEC);
140 rmtp->tv_nsec = (long) ((timeout.QuadPart % NS100PERSEC)
141 * (NSPERSEC/NS100PERSEC));
143 __except (NO_ERROR)
145 res = EFAULT;
147 __endtry
150 syscall_printf ("%d = clock_nanosleep(%lu, %d, %ld.%09ld, %ld.%09.ld)",
151 res, clk_id, flags, rqtp->tv_sec, rqtp->tv_nsec,
152 rmtp ? rmtp->tv_sec : 0, rmtp ? rmtp->tv_nsec : 0);
153 return res;
156 extern "C" int
157 nanosleep (const struct timespec *rqtp, struct timespec *rmtp)
159 int res = clock_nanosleep (CLOCK_REALTIME, 0, rqtp, rmtp);
160 if (res != 0)
162 set_errno (res);
163 return -1;
165 return 0;
168 extern "C" unsigned int
169 sleep (unsigned int seconds)
171 struct timespec req, rem;
172 req.tv_sec = seconds;
173 req.tv_nsec = 0;
174 if (clock_nanosleep (CLOCK_REALTIME, 0, &req, &rem))
175 return rem.tv_sec + (rem.tv_nsec > 0);
176 return 0;
179 extern "C" int
180 usleep (useconds_t useconds)
182 struct timespec req;
183 req.tv_sec = useconds / USPERSEC;
184 req.tv_nsec = (useconds % USPERSEC) * (NSPERSEC/USPERSEC);
185 int res = clock_nanosleep (CLOCK_REALTIME, 0, &req, NULL);
186 if (res != 0)
188 set_errno (res);
189 return -1;
191 return 0;
194 extern "C" int
195 sigprocmask (int how, const sigset_t *set, sigset_t *oldset)
197 int res = handle_sigprocmask (how, set, oldset, _my_tls.sigmask);
198 if (res)
200 set_errno (res);
201 res = -1;
203 syscall_printf ("%R = sigprocmask (%d, %p, %p)", res, how, set, oldset);
204 return res;
208 handle_sigprocmask (int how, const sigset_t *set, sigset_t *oldset, sigset_t& opmask)
210 /* check that how is in right range if set is not NULL */
211 if (set && how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK)
213 syscall_printf ("Invalid how value %d", how);
214 return EINVAL;
217 __try
219 if (oldset)
220 *oldset = opmask;
222 if (set)
224 sigset_t newmask = opmask;
225 switch (how)
227 case SIG_BLOCK:
228 /* add set to current mask */
229 newmask |= *set;
230 break;
231 case SIG_UNBLOCK:
232 /* remove set from current mask */
233 newmask &= ~*set;
234 break;
235 case SIG_SETMASK:
236 /* just set it */
237 newmask = *set;
238 break;
240 set_signal_mask (opmask, newmask);
243 __except (EFAULT)
245 return EFAULT;
247 __endtry
248 return 0;
252 _pinfo::kill (siginfo_t& si)
254 int res;
255 DWORD this_process_state;
256 pid_t this_pid;
258 sig_dispatch_pending ();
260 if (exists ())
262 bool sendSIGCONT;
263 this_process_state = process_state;
264 if ((sendSIGCONT = (si.si_signo < 0)))
265 si.si_signo = -si.si_signo;
267 if (si.si_signo == 0)
268 res = 0;
269 else if ((res = (int) sig_send (this, si)))
271 sigproc_printf ("%d = sig_send, %E ", res);
272 res = -1;
274 else if (sendSIGCONT)
276 siginfo_t si2 = {0};
277 si2.si_signo = SIGCONT;
278 si2.si_code = SI_KERNEL;
279 sig_send (this, si2);
281 this_pid = pid;
283 else if (process_state == PID_EXITED)
285 this_process_state = process_state;
286 this_pid = pid;
287 res = 0;
289 else
291 set_errno (ESRCH);
292 this_process_state = 0;
293 this_pid = 0;
294 res = -1;
297 syscall_printf ("%d = _pinfo::kill (%d), pid %d, process_state %y", res,
298 si.si_signo, this_pid, this_process_state);
299 return res;
302 extern "C" int
303 raise (int sig)
305 pthread *thread = _my_tls.tid;
306 if (!thread || !__isthreaded)
307 return kill (myself->pid, sig);
309 /* Make sure to return -1 and set errno, as on Linux. */
310 int err = pthread_kill (thread, sig);
311 if (err)
312 set_errno (err);
313 return err ? -1 : 0;
316 static int
317 kill0 (pid_t pid, siginfo_t& si)
319 syscall_printf ("kill (%d, %d)", pid, si.si_signo);
320 /* check that sig is in right range */
321 if (si.si_signo < 0 || si.si_signo >= _NSIG)
323 set_errno (EINVAL);
324 syscall_printf ("signal %d out of range", si.si_signo);
325 return -1;
327 if (pid > 0)
329 pinfo p (pid);
330 if (!p)
332 set_errno (ESRCH);
333 return -1;
335 return p->kill (si);
337 return kill_pgrp (-pid, si);
341 kill (pid_t pid, int sig)
343 siginfo_t si = {0};
344 si.si_signo = sig;
345 si.si_code = SI_USER;
346 return kill0 (pid, si);
350 kill_pgrp (pid_t pid, siginfo_t& si)
352 int res = 0;
353 int found = 0;
354 int killself = 0;
356 sigproc_printf ("pid %d, signal %d", pid, si.si_signo);
358 winpids pids ((DWORD) PID_MAP_RW);
359 for (unsigned i = 0; i < pids.npids; i++)
361 _pinfo *p = pids[i];
363 if (!p || !p->exists ())
364 continue;
366 /* Is it a process we want to kill? */
367 if ((pid == 0 && (p->pgid != myself->pgid || p->ctty != myself->ctty)) ||
368 (pid > 1 && p->pgid != pid) ||
369 (si.si_signo < 0 && NOTSTATE (p, PID_STOPPED)))
370 continue;
371 sigproc_printf ("killing pid %d, pgrp %d, p->%s, %s", p->pid, p->pgid,
372 p->__ctty (), myctty ());
373 if (p == myself)
374 killself++;
375 else if (p->kill (si))
376 res = -1;
377 found++;
380 if (killself && !exit_state && myself->kill (si))
381 res = -1;
383 if (!found)
385 set_errno (ESRCH);
386 res = -1;
388 syscall_printf ("%R = kill(%d, %d)", res, pid, si.si_signo);
389 return res;
392 extern "C" int
393 killpg (pid_t pgrp, int sig)
395 return kill (-pgrp, sig);
398 extern "C" void
399 abort (void)
401 _my_tls.incyg++;
402 sig_dispatch_pending ();
403 /* Ensure that SIGABRT can be caught regardless of blockage. */
404 sigset_t sig_mask;
405 sigfillset (&sig_mask);
406 sigdelset (&sig_mask, SIGABRT);
407 set_signal_mask (_my_tls.sigmask, sig_mask);
409 raise (SIGABRT);
410 _my_tls.call_signal_handler (); /* Call any signal handler */
412 /* Flush all streams as per SUSv2. */
413 if (__stdio_exit_handler)
414 (*__stdio_exit_handler) ();
415 do_exit (SIGABRT); /* signal handler didn't exit. Goodbye. */
418 static int
419 sigaction_worker (int sig, const struct sigaction *newact,
420 struct sigaction *oldact, bool isinternal)
422 int res = -1;
423 __try
425 sig_dispatch_pending ();
426 /* check that sig is in right range */
427 if (sig <= 0 || sig >= _NSIG)
428 set_errno (EINVAL);
429 else
431 struct sigaction oa = global_sigs[sig];
433 if (!newact)
434 sigproc_printf ("signal %d, newact %p, oa %p",
435 sig, newact, oa, oa.sa_handler);
436 else
438 sigproc_printf ("signal %d, newact %p (handler %p), oa %p",
439 sig, newact, newact->sa_handler, oa,
440 oa.sa_handler);
441 if (sig == SIGKILL || sig == SIGSTOP)
443 set_errno (EINVAL);
444 __leave;
446 struct sigaction na = *newact;
447 struct sigaction& gs = global_sigs[sig];
448 if (!isinternal)
449 na.sa_flags &= ~_SA_INTERNAL_MASK;
450 gs = na;
451 if (!(gs.sa_flags & SA_NODEFER))
452 gs.sa_mask |= SIGTOMASK(sig);
453 if (gs.sa_handler == SIG_IGN)
454 sig_clear (sig);
455 if (gs.sa_handler == SIG_DFL && sig == SIGCHLD)
456 sig_clear (sig);
457 if (sig == SIGCHLD)
459 myself->process_state &= ~PID_NOCLDSTOP;
460 if (gs.sa_flags & SA_NOCLDSTOP)
461 myself->process_state |= PID_NOCLDSTOP;
465 if (oldact)
467 *oldact = oa;
468 oa.sa_flags &= ~_SA_INTERNAL_MASK;
470 res = 0;
473 __except (EFAULT) {}
474 __endtry
475 return res;
478 extern "C" int
479 sigaction (int sig, const struct sigaction *newact, struct sigaction *oldact)
481 int res = sigaction_worker (sig, newact, oldact, false);
482 syscall_printf ("%R = sigaction(%d, %p, %p)", res, sig, newact, oldact);
483 return res;
486 extern "C" int
487 sigaddset (sigset_t *set, const int sig)
489 /* check that sig is in right range */
490 if (sig <= 0 || sig >= _NSIG)
492 set_errno (EINVAL);
493 syscall_printf ("SIG_ERR = sigaddset signal %d out of range", sig);
494 return -1;
497 *set |= SIGTOMASK (sig);
498 return 0;
501 extern "C" int
502 sigdelset (sigset_t *set, const int sig)
504 /* check that sig is in right range */
505 if (sig <= 0 || sig >= _NSIG)
507 set_errno (EINVAL);
508 syscall_printf ("SIG_ERR = sigdelset signal %d out of range", sig);
509 return -1;
512 *set &= ~SIGTOMASK (sig);
513 return 0;
516 extern "C" int
517 sigismember (const sigset_t *set, int sig)
519 /* check that sig is in right range */
520 if (sig <= 0 || sig >= _NSIG)
522 set_errno (EINVAL);
523 syscall_printf ("SIG_ERR = sigdelset signal %d out of range", sig);
524 return -1;
527 if (*set & SIGTOMASK (sig))
528 return 1;
529 else
530 return 0;
533 extern "C" int
534 sigemptyset (sigset_t *set)
536 *set = (sigset_t) 0;
537 return 0;
540 extern "C" int
541 sigfillset (sigset_t *set)
543 *set = ~((sigset_t) 0);
544 return 0;
547 extern "C" int
548 sigsuspend (const sigset_t *set)
550 int res = handle_sigsuspend (*set);
551 syscall_printf ("%R = sigsuspend(%p)", res, set);
552 return res;
555 extern "C" int
556 sigpause (int signal_mask)
558 int res = handle_sigsuspend ((sigset_t) signal_mask);
559 syscall_printf ("%R = sigpause(%y)", res, signal_mask);
560 return res;
563 extern "C" int
564 __xpg_sigpause (int sig)
566 int res;
567 sigset_t signal_mask;
568 sigprocmask (0, NULL, &signal_mask);
569 sigdelset (&signal_mask, sig);
570 res = handle_sigsuspend (signal_mask);
571 syscall_printf ("%R = __xpg_sigpause(%y)", res, sig);
572 return res;
575 extern "C" int
576 pause (void)
578 int res = handle_sigsuspend (_my_tls.sigmask);
579 syscall_printf ("%R = pause()", res);
580 return res;
583 extern "C" int
584 siginterrupt (int sig, int flag)
586 struct sigaction act;
587 int res = sigaction_worker (sig, NULL, &act, false);
588 if (res == 0)
590 if (flag)
592 act.sa_flags &= ~SA_RESTART;
593 act.sa_flags |= _SA_NORESTART;
595 else
597 act.sa_flags &= ~_SA_NORESTART;
598 act.sa_flags |= SA_RESTART;
600 res = sigaction_worker (sig, &act, NULL, true);
602 syscall_printf ("%R = siginterrupt(%d, %y)", sig, flag);
603 return res;
607 sigwait_common (const sigset_t *set, siginfo_t *info, PLARGE_INTEGER waittime)
609 int res = -1;
611 pthread_testcancel ();
613 __try
615 set_signal_mask (_my_tls.sigwait_mask, *set);
616 sig_dispatch_pending (true);
618 switch (cygwait (NULL, waittime,
619 cw_sig_eintr | cw_cancel | cw_cancel_self))
621 case WAIT_SIGNALED:
622 if (!sigismember (set, _my_tls.infodata.si_signo))
623 set_errno (EINTR);
624 else
626 _my_tls.lock ();
627 if (_my_tls.infodata.si_code == SI_TIMER)
629 timer_tracker *tt = (timer_tracker *)
630 _my_tls.infodata.si_tid;
631 _my_tls.infodata.si_overrun = tt->disarm_overrun_event ();
633 if (info)
634 *info = _my_tls.infodata;
635 res = _my_tls.infodata.si_signo;
636 _my_tls.sig = 0;
637 if (_my_tls.retaddr () == (__tlsstack_t) sigdelayed)
638 _my_tls.pop ();
639 _my_tls.unlock ();
641 break;
642 case WAIT_TIMEOUT:
643 set_errno (EAGAIN);
644 break;
645 default:
646 __seterrno ();
647 break;
650 __except (EFAULT)
652 res = -1;
654 __endtry
655 sigproc_printf ("returning signal %d", res);
656 return res;
659 extern "C" int
660 sigtimedwait (const sigset_t *set, siginfo_t *info, const timespec *timeout)
662 LARGE_INTEGER waittime;
664 if (timeout)
666 if (!valid_timespec (*timeout))
668 set_errno (EINVAL);
669 return -1;
671 /* convert timespec to 100ns units */
672 waittime.QuadPart = (LONGLONG) timeout->tv_sec * NS100PERSEC
673 + ((LONGLONG) timeout->tv_nsec + (NSPERSEC/NS100PERSEC) - 1)
674 / (NSPERSEC/NS100PERSEC);
675 /* negate waittime to code as duration for NtSetTimer() below cygwait() */
676 waittime.QuadPart = -waittime.QuadPart;
679 return sigwait_common (set, info, timeout ? &waittime : cw_infinite);
682 extern "C" int
683 sigwait (const sigset_t *set, int *sig_ptr)
685 int sig;
689 sig = sigwait_common (set, NULL, cw_infinite);
691 while (sig == -1 && get_errno () == EINTR);
692 if (sig > 0)
693 *sig_ptr = sig;
694 return sig > 0 ? 0 : get_errno ();
697 extern "C" int
698 sigwaitinfo (const sigset_t *set, siginfo_t *info)
700 return sigwait_common (set, info, cw_infinite);
703 /* FIXME: SUSv3 says that this function should block until the signal has
704 actually been delivered. Currently, this will only happen when sending
705 signals to the current process. It will not happen when sending signals
706 to other processes. */
707 extern "C" int
708 sigqueue (pid_t pid, int sig, const union sigval value)
710 siginfo_t si = {0};
711 pinfo dest (pid);
712 if (!dest)
714 set_errno (ESRCH);
715 return -1;
717 if (sig == 0)
718 return 0;
719 if (sig < 0 || sig >= _NSIG)
721 set_errno (EINVAL);
722 return -1;
724 si.si_signo = sig;
725 si.si_code = SI_QUEUE;
726 si.si_value = value;
727 return (int) sig_send (dest, si);
730 extern "C" int
731 sigaltstack (const stack_t *ss, stack_t *oss)
733 _cygtls& me = _my_tls;
735 __try
737 if (ss)
739 if (me.altstack.ss_flags == SS_ONSTACK)
741 /* An attempt was made to modify an active stack. */
742 set_errno (EPERM);
743 return -1;
745 if (ss->ss_flags == SS_DISABLE)
747 me.altstack.ss_sp = NULL;
748 me.altstack.ss_flags = 0;
749 me.altstack.ss_size = 0;
751 else
753 if (ss->ss_flags)
755 /* The ss argument is not a null pointer, and the ss_flags
756 member pointed to by ss contains flags other than
757 SS_DISABLE. */
758 set_errno (EINVAL);
759 return -1;
761 if (ss->ss_size < MINSIGSTKSZ)
763 /* The size of the alternate stack area is less than
764 MINSIGSTKSZ. */
765 set_errno (ENOMEM);
766 return -1;
768 memcpy (&me.altstack, ss, sizeof *ss);
771 if (oss)
773 char stack_marker;
774 memcpy (oss, &me.altstack, sizeof *oss);
775 /* Check if the current stack is the alternate signal stack. If so,
776 set ss_flags accordingly. We do this here rather than setting
777 ss_flags in _cygtls::call_signal_handler since the signal handler
778 calls longjmp, so we never return to reset the flag. */
779 if (!me.altstack.ss_flags && me.altstack.ss_sp)
781 if (&stack_marker >= (char *) me.altstack.ss_sp
782 && &stack_marker < (char *) me.altstack.ss_sp
783 + me.altstack.ss_size)
784 oss->ss_flags = SS_ONSTACK;
788 __except (EFAULT)
790 return EFAULT;
792 __endtry
793 return 0;
796 extern "C" int
797 signalfd (int fd_in, const sigset_t *mask, int flags)
799 int ret = -1;
800 fhandler_signalfd *fh;
802 debug_printf ("signalfd (%d, %p, %y)", fd_in, mask, flags);
804 if ((flags & ~(SFD_NONBLOCK | SFD_CLOEXEC)) != 0)
806 set_errno (EINVAL);
807 goto done;
810 if (fd_in != -1)
812 /* Change signal mask. */
813 cygheap_fdget fd (fd_in);
815 if (fd < 0)
816 goto done;
817 fh = fd->is_signalfd ();
818 if (!fh)
820 set_errno (EINVAL);
821 goto done;
823 __try
825 if (fh->signalfd (mask, flags) == 0)
826 ret = fd_in;
828 __except (EINVAL) {}
829 __endtry
831 else
833 /* Create new signalfd descriptor. */
834 cygheap_fdnew fd;
836 if (fd < 0)
837 goto done;
838 fh = (fhandler_signalfd *) build_fh_dev (*signalfd_dev);
839 if (fh && fh->signalfd (mask, flags) == 0)
841 fd = fh;
842 if (fd <= 2)
843 set_std_handle (fd);
844 ret = fd;
846 else
847 delete fh;
850 done:
851 syscall_printf ("%R = signalfd (%d, %p, %y)", ret, fd_in, mask, flags);
852 return ret;