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
15 #include <sys/cygwin.h>
16 #include <sys/signalfd.h>
17 #include <sys/reent.h> /* needed for __stdio_exit_handler declaration */
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 ();
40 /* check that sig is in right range */
41 if (sig
<= 0 || sig
>= _NSIG
|| sig
== SIGKILL
|| sig
== SIGSTOP
)
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
;
53 gs
.sa_flags
|= SA_RESTART
;
55 gs
.sa_mask
= SIGTOMASK (sig
);
57 gs
.sa_flags
&= ~SA_SIGINFO
;
59 syscall_printf ("%p = signal (%d, %p)", prev
, sig
, func
);
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;
69 sig_dispatch_pending ();
70 pthread_testcancel ();
74 if (!valid_timespec (*rqtp
))
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
)
88 /* support for CPU-time clocks is optional */
89 if (CLOCKID_IS_PROCESS (clk_id
) || CLOCKID_IS_THREAD (clk_id
))
91 /* All other valid clocks are valid */
92 if (clk_id
>= MAX_CLOCKS
)
95 LARGE_INTEGER timeout
;
97 timeout
.QuadPart
= (LONGLONG
) rqtp
->tv_sec
* NS100PERSEC
98 + ((LONGLONG
) rqtp
->tv_nsec
+ (NSPERSEC
/NS100PERSEC
) - 1)
99 / (NSPERSEC
/NS100PERSEC
);
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
))
113 case CLOCK_REALTIME_COARSE
:
115 timeout
.QuadPart
+= FACTOR
;
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;
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
)
134 /* according to POSIX, rmtp is used only if !abstime */
135 if (rmtp
&& !abstime
)
139 rmtp
->tv_sec
= (time_t) (timeout
.QuadPart
/ NS100PERSEC
);
140 rmtp
->tv_nsec
= (long) ((timeout
.QuadPart
% NS100PERSEC
)
141 * (NSPERSEC
/NS100PERSEC
));
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);
157 nanosleep (const struct timespec
*rqtp
, struct timespec
*rmtp
)
159 int res
= clock_nanosleep (CLOCK_REALTIME
, 0, rqtp
, rmtp
);
168 extern "C" unsigned int
169 sleep (unsigned int seconds
)
171 struct timespec req
, rem
;
172 req
.tv_sec
= seconds
;
174 if (clock_nanosleep (CLOCK_REALTIME
, 0, &req
, &rem
))
175 return rem
.tv_sec
+ (rem
.tv_nsec
> 0);
180 usleep (useconds_t useconds
)
183 req
.tv_sec
= useconds
/ USPERSEC
;
184 req
.tv_nsec
= (useconds
% USPERSEC
) * (NSPERSEC
/USPERSEC
);
185 int res
= clock_nanosleep (CLOCK_REALTIME
, 0, &req
, NULL
);
195 sigprocmask (int how
, const sigset_t
*set
, sigset_t
*oldset
)
197 int res
= handle_sigprocmask (how
, set
, oldset
, _my_tls
.sigmask
);
203 syscall_printf ("%R = sigprocmask (%d, %p, %p)", res
, how
, set
, oldset
);
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
);
224 sigset_t newmask
= opmask
;
228 /* add set to current mask */
232 /* remove set from current mask */
240 set_signal_mask (opmask
, newmask
);
252 _pinfo::kill (siginfo_t
& si
)
255 DWORD this_process_state
;
258 sig_dispatch_pending ();
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)
269 else if ((res
= (int) sig_send (this, si
)))
271 sigproc_printf ("%d = sig_send, %E ", res
);
274 else if (sendSIGCONT
)
277 si2
.si_signo
= SIGCONT
;
278 si2
.si_code
= SI_KERNEL
;
279 sig_send (this, si2
);
283 else if (process_state
== PID_EXITED
)
285 this_process_state
= process_state
;
292 this_process_state
= 0;
297 syscall_printf ("%d = _pinfo::kill (%d), pid %d, process_state %y", res
,
298 si
.si_signo
, this_pid
, this_process_state
);
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
);
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
)
324 syscall_printf ("signal %d out of range", si
.si_signo
);
337 return kill_pgrp (-pid
, si
);
341 kill (pid_t pid
, int sig
)
345 si
.si_code
= SI_USER
;
346 return kill0 (pid
, si
);
350 kill_pgrp (pid_t pid
, siginfo_t
& si
)
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
++)
363 if (!p
|| !p
->exists ())
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
)))
371 sigproc_printf ("killing pid %d, pgrp %d, p->%s, %s", p
->pid
, p
->pgid
,
372 p
->__ctty (), myctty ());
375 else if (p
->kill (si
))
380 if (killself
&& !exit_state
&& myself
->kill (si
))
388 syscall_printf ("%R = kill(%d, %d)", res
, pid
, si
.si_signo
);
393 killpg (pid_t pgrp
, int sig
)
395 return kill (-pgrp
, sig
);
402 sig_dispatch_pending ();
403 /* Ensure that SIGABRT can be caught regardless of blockage. */
405 sigfillset (&sig_mask
);
406 sigdelset (&sig_mask
, SIGABRT
);
407 set_signal_mask (_my_tls
.sigmask
, sig_mask
);
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. */
419 sigaction_worker (int sig
, const struct sigaction
*newact
,
420 struct sigaction
*oldact
, bool isinternal
)
425 sig_dispatch_pending ();
426 /* check that sig is in right range */
427 if (sig
<= 0 || sig
>= _NSIG
)
431 struct sigaction oa
= global_sigs
[sig
];
434 sigproc_printf ("signal %d, newact %p, oa %p",
435 sig
, newact
, oa
, oa
.sa_handler
);
438 sigproc_printf ("signal %d, newact %p (handler %p), oa %p",
439 sig
, newact
, newact
->sa_handler
, oa
,
441 if (sig
== SIGKILL
|| sig
== SIGSTOP
)
446 struct sigaction na
= *newact
;
447 struct sigaction
& gs
= global_sigs
[sig
];
449 na
.sa_flags
&= ~_SA_INTERNAL_MASK
;
451 if (!(gs
.sa_flags
& SA_NODEFER
))
452 gs
.sa_mask
|= SIGTOMASK(sig
);
453 if (gs
.sa_handler
== SIG_IGN
)
455 if (gs
.sa_handler
== SIG_DFL
&& sig
== SIGCHLD
)
459 myself
->process_state
&= ~PID_NOCLDSTOP
;
460 if (gs
.sa_flags
& SA_NOCLDSTOP
)
461 myself
->process_state
|= PID_NOCLDSTOP
;
468 oa
.sa_flags
&= ~_SA_INTERNAL_MASK
;
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
);
487 sigaddset (sigset_t
*set
, const int sig
)
489 /* check that sig is in right range */
490 if (sig
<= 0 || sig
>= _NSIG
)
493 syscall_printf ("SIG_ERR = sigaddset signal %d out of range", sig
);
497 *set
|= SIGTOMASK (sig
);
502 sigdelset (sigset_t
*set
, const int sig
)
504 /* check that sig is in right range */
505 if (sig
<= 0 || sig
>= _NSIG
)
508 syscall_printf ("SIG_ERR = sigdelset signal %d out of range", sig
);
512 *set
&= ~SIGTOMASK (sig
);
517 sigismember (const sigset_t
*set
, int sig
)
519 /* check that sig is in right range */
520 if (sig
<= 0 || sig
>= _NSIG
)
523 syscall_printf ("SIG_ERR = sigdelset signal %d out of range", sig
);
527 if (*set
& SIGTOMASK (sig
))
534 sigemptyset (sigset_t
*set
)
541 sigfillset (sigset_t
*set
)
543 *set
= ~((sigset_t
) 0);
548 sigsuspend (const sigset_t
*set
)
550 int res
= handle_sigsuspend (*set
);
551 syscall_printf ("%R = sigsuspend(%p)", res
, set
);
556 sigpause (int signal_mask
)
558 int res
= handle_sigsuspend ((sigset_t
) signal_mask
);
559 syscall_printf ("%R = sigpause(%y)", res
, signal_mask
);
564 __xpg_sigpause (int sig
)
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
);
578 int res
= handle_sigsuspend (_my_tls
.sigmask
);
579 syscall_printf ("%R = pause()", res
);
584 siginterrupt (int sig
, int flag
)
586 struct sigaction act
;
587 int res
= sigaction_worker (sig
, NULL
, &act
, false);
592 act
.sa_flags
&= ~SA_RESTART
;
593 act
.sa_flags
|= _SA_NORESTART
;
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
);
607 sigwait_common (const sigset_t
*set
, siginfo_t
*info
, PLARGE_INTEGER waittime
)
611 pthread_testcancel ();
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
))
622 if (!sigismember (set
, _my_tls
.infodata
.si_signo
))
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 ();
634 *info
= _my_tls
.infodata
;
635 res
= _my_tls
.infodata
.si_signo
;
637 if (_my_tls
.retaddr () == (__tlsstack_t
) sigdelayed
)
655 sigproc_printf ("returning signal %d", res
);
660 sigtimedwait (const sigset_t
*set
, siginfo_t
*info
, const timespec
*timeout
)
662 LARGE_INTEGER waittime
;
666 if (!valid_timespec (*timeout
))
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
);
683 sigwait (const sigset_t
*set
, int *sig_ptr
)
689 sig
= sigwait_common (set
, NULL
, cw_infinite
);
691 while (sig
== -1 && get_errno () == EINTR
);
694 return sig
> 0 ? 0 : get_errno ();
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. */
708 sigqueue (pid_t pid
, int sig
, const union sigval value
)
719 if (sig
< 0 || sig
>= _NSIG
)
725 si
.si_code
= SI_QUEUE
;
727 return (int) sig_send (dest
, si
);
731 sigaltstack (const stack_t
*ss
, stack_t
*oss
)
733 _cygtls
& me
= _my_tls
;
739 if (me
.altstack
.ss_flags
== SS_ONSTACK
)
741 /* An attempt was made to modify an active stack. */
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;
755 /* The ss argument is not a null pointer, and the ss_flags
756 member pointed to by ss contains flags other than
761 if (ss
->ss_size
< MINSIGSTKSZ
)
763 /* The size of the alternate stack area is less than
768 memcpy (&me
.altstack
, ss
, sizeof *ss
);
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
;
797 signalfd (int fd_in
, const sigset_t
*mask
, int flags
)
800 fhandler_signalfd
*fh
;
802 debug_printf ("signalfd (%d, %p, %y)", fd_in
, mask
, flags
);
804 if ((flags
& ~(SFD_NONBLOCK
| SFD_CLOEXEC
)) != 0)
812 /* Change signal mask. */
813 cygheap_fdget
fd (fd_in
);
817 fh
= fd
->is_signalfd ();
825 if (fh
->signalfd (mask
, flags
) == 0)
833 /* Create new signalfd descriptor. */
838 fh
= (fhandler_signalfd
*) build_fh_dev (*signalfd_dev
);
839 if (fh
&& fh
->signalfd (mask
, flags
) == 0)
851 syscall_printf ("%R = signalfd (%d, %p, %y)", ret
, fd_in
, mask
, flags
);