'\" t
-.\" Copyright (c) 2001, Michael Kerrisk <mtk.manpages@gmail.com>
+.\" Copyright (c) 2001, 2017 Michael Kerrisk <mtk.manpages@gmail.com>
.\"
.\" %%%LICENSE_START(VERBATIM)
.\" Permission is granted to make and distribute verbatim copies of this
.\" %%%LICENSE_END
.\"
.\" aeb, various minor fixes
-.TH SIGALTSTACK 2 2017-07-13 "Linux" "Linux Programmer's Manual"
+.TH SIGALTSTACK 2 2017-11-08 "Linux" "Linux Programmer's Manual"
.SH NAME
sigaltstack \- set and/or get signal stack context
.SH SYNOPSIS
.B #include <signal.h>
-.sp
+.PP
.BI "int sigaltstack(const stack_t *" ss ", stack_t *" old_ss );
.PP
.in -4n
inform the system that the signal handler should be executed
on the alternate signal stack by
specifying the \fBSA_ONSTACK\fP flag.
-.P
+.PP
The \fIss\fP argument is used to specify a new
alternate signal stack, while the \fIold_ss\fP argument
is used to retrieve information about the currently
The
.I stack_t
type used to type the arguments of this function is defined as follows:
-
+.PP
.in +4n
-.nf
+.EX
typedef struct {
void *ss_sp; /* Base address of stack */
int ss_flags; /* Flags */
size_t ss_size; /* Number of bytes in stack */
} stack_t;
-.fi
+.EE
.in
-
+.PP
To establish a new alternate signal stack,
the fields of this structure are set as follows:
.TP
.I ss.ss_flags
-This field is set to zero.
+This field contains either 0, or the following flag:
+.RS
+.TP
+.BR SS_AUTODISARM " (since Linux 4.7)"
+.\" commit 2a74213838104a41588d86fd5e8d344972891ace
+.\" See tools/testing/selftests/sigaltstack/sas.c in kernel sources
+Clear the alternate signal stack settings on entry to the signal handler.
+When the signal handler returns,
+the previous alternate signal stack settings are restored.
+.IP
+This flag was added in order make it safe
+to switch away from the signal handler with
+.BR swapcontext (3).
+Without this flag, a subsequently handled signal will corrupt
+the state of the switched-away signal handler.
+On kernels where this flag is not supported,
+.BR sigaltstack ()
+fails with the error
+.BR EINVAL
+when this flag is supplied.
+.RE
.TP
.I ss.ss_sp
This field specifies the starting address of the stack.
.PP
To disable an existing stack, specify \fIss.ss_flags\fP
as \fBSS_DISABLE\fP.
-In this case, the remaining fields
-in \fIss\fP are ignored.
+In this case, the kernel ignores any other flags in
+.IR ss.ss_flags
+and the remaining fields
+in \fIss\fP.
.PP
If \fIold_ss\fP is not NULL, then it is used to return information about
the alternate signal stack which was in effect prior to the
.TP
.B SS_DISABLE
The alternate signal stack is currently disabled.
+.IP
+Alternatively, this value is returned if the process is currently
+executing on an alternate signal stack that was established using the
+.B SS_AUTODISARM
+flag.
+In this case, it is safe to switch away from the signal handler with
+.BR swapcontext (3).
+It is also possible to set up a different alternative signal stack
+using a further call to
+.BR sigaltstack ().
+.\" FIXME Was it intended that one can set up a different alternative
+.\" signal stack in this scenario? (In passing, if one does this, the
+.\" sigaltstack(NULL, &old_ss) now returns old_ss.ss_flags==SS_AUTODISARM
+.\" rather than old_ss.ss_flags==SS_DISABLE. The API design here seems
+.\" confusing...
+.TP
+.B SS_AUTODISARM
+The alternate signal stack has been marked to be autodisarmed
+as described above.
.PP
By specifying
.I ss
The specified size of the new alternate signal stack
.I ss.ss_size
was less than
-.BR MINSTKSZ .
+.BR MINSIGSTKSZ .
.TP
.B EPERM
An attempt was made to change the alternate signal stack while
T} Thread safety MT-Safe
.TE
.SH CONFORMING TO
-POSIX.1-2001, POSIX.1-2009, SUSv2, SVr4.
+POSIX.1-2001, POSIX.1-2008, SUSv2, SVr4.
+.PP
+The
+.B SS_AUTODISARM
+flag is a Linux extension.
.SH NOTES
The most common usage of an alternate signal stack is to handle the
.B SIGSEGV
.B SIGSEGV
cannot be invoked on the process stack; if we wish to handle it,
we must use an alternate signal stack.
-.P
+.PP
Establishing an alternate signal stack is useful if a process
expects that it may exhaust its standard stack.
This may occur, for example, because the stack grows so large
the process a \fBSIGSEGV\fP signal.
In these circumstances the only way to catch this signal is
on an alternate signal stack.
-.P
+.PP
On most hardware architectures supported by Linux, stacks grow
downward.
.BR sigaltstack ()
automatically takes account
of the direction of stack growth.
-.P
+.PP
Functions called from a signal handler executing on an alternate
signal stack will also use the alternate signal stack.
(This also applies to any handlers invoked for other signals while
automatically extend the alternate signal stack.
Exceeding the allocated size of the alternate signal stack will
lead to unpredictable results.
-.P
+.PP
A successful call to
.BR execve (2)
removes any existing alternate
A child process created via
.BR fork (2)
inherits a copy of its parent's alternate signal stack settings.
-.P
+.PP
.BR sigaltstack ()
supersedes the older
.BR sigstack ()
had to know the direction of stack growth.
.SH EXAMPLE
The following code segment demonstrates the use of
-.BR sigaltstack ():
-
+.BR sigaltstack ()
+(and
+.BR sigaction (2))
+to install an alternate signal stack that is employed by a handler
+for the
+.BR SIGSEGV
+signal:
+.PP
.in +4n
-.nf
+.EX
stack_t ss;
ss.ss_sp = malloc(SIGSTKSZ);
-if (ss.ss_sp == NULL)
- /* Handle error */;
+if (ss.ss_sp == NULL) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+}
+
ss.ss_size = SIGSTKSZ;
ss.ss_flags = 0;
-if (sigaltstack(&ss, NULL) == \-1)
- /* Handle error */;
-.fi
+if (sigaltstack(&ss, NULL) == \-1) {
+ perror("sigaltstack");
+ exit(EXIT_FAILURE);
+}
+
+sa.sa_flags = SA_ONSTACK;
+sa.sa_handler = handler(); /* Address of a signal handler */
+sigemptyset(&sa.sa_mask);
+if (sigaction(SIGSEGV, &sa, NULL) == -1) {
+ perror("sigaction");
+ exit(EXIT_FAILURE);
+}
+.EE
.in
.SH BUGS
-In the lead up to the development of the Linux 2.4 kernel,
+In Linux 2.2 and earlier, the only flag that could be specified
+in
+.I ss.sa_flags
+was
+.BR SS_DISABLE .
+In the lead up to the release of the Linux 2.4 kernel,
.\" Linux 2.3.40
-someone got confused and allowed the kernel to accept
+.\" After quite a bit of web and mail archive searching,
+.\" I could not find the patch on any mailing list, and I
+.\" could find no place where the rationale for this change
+.\" explained -- mtk
+a change was made to allow
+.BR sigaltstack ()
+to allow
+.I ss.ss_flags==SS_ONSTACK
+with the same meaning as
+.IR "ss.ss_flags==0"
+(i.e., the inclusion of
.B SS_ONSTACK
in
-.IR ss.ss_flags ,
-which results in behavior that is the same as when
-.I ss_flags
-is 0.
+.I ss.ss_flags
+is a no-op).
On other implementations, and according to POSIX.1,
.B SS_ONSTACK
appears only as a reported flag in
.IR old_ss.ss_flags .
-There is no need ever to specify this flag in
-.IR ss.ss_flags
-(and indeed, doing so decreases portability,
-since some implementations
+On Linux, there is no need ever to specify
+.B SS_ONSTACK
+in
+.IR ss.ss_flags ,
+and indeed doing so should be avoided on portability grounds:
+various other systems
.\" See the source code of Illumos and FreeBSD, for example.
give an error if
.B SS_ONSTACK
is specified in
-.IR ss.ss_flags ).
+.IR ss.ss_flags .
.SH SEE ALSO
.BR execve (2),
.BR setrlimit (2),