NOTIFY(2)NOTIFY(2)
NAME
notify, noted, atnotify – handle asynchronous process notification
SYNOPSIS
#include <u.h>
#include <libc.h>
int notify(void (*f)(void*, char*))
int noted(int v)
int atnotify(int (*f)(void*, char*), int in)
DESCRIPTION
When a process raises an exceptional condition such as dividing by zero
or writing on a closed pipe, a
note
is posted to communicate the exception.
A note may also be posted by a
write
(see
read(2))
to the process’s
/proc/n/note
file or to the
/proc/m/notepg
file of a process in the same process group (see
proc(3)).
When the note is received
the behavior of the process depends on the origin of the note.
If the note was posted by an external process,
the process receiving the note exits;
if generated by the system the note string,
preceded by the name
and id of the process and the string
"suicide: ",
is printed on the process’s standard error file
and the
process is suspended in the
Broken
state for debugging.
These default actions may be overridden.
The
notify
function registers a
notification handler
to be called within the process when a note is received.
The argument to
notify
replaces the previous handler, if any.
An argument of zero cancels a previous handler,
restoring the default action.
A
fork(2)
system call leaves the handler registered in
both the parent and the child;
exec(2)
restores the default behavior.
Handlers may not perform floating point operations.
After a note is posted,
the handler is called with two arguments:
the first is a pointer to a
Ureg
structure (defined in
/$objtype/include/ureg.h)
giving the current values of registers;
the second is a pointer to the note itself,
a null-terminated string with no more than
ERRLEN
characters in it including the terminal NUL.
The
Ureg
argument is usually not needed; it is provided to help recover from traps such
as floating point exceptions.
Its use and layout are machine- and system-specific.
A notification handler must finish either by exiting the program or by calling
noted;
if the handler returns the behavior
is undefined and probably erroneous.
Until the program calls
noted,
any further externally-generated notes
(e.g.,
hangup
or
alarm)
will be held off, and any further notes generated by
erroneous behavior by the program
(such as divide by zero) will kill the program.
The argument to
noted
defines the action to take:
NDFLT
instructs the system to perform the default action
as if the handler had never been registered;
NCONT
instructs the system to resume the process
at the point it was notified.
In neither case does
noted
return to the handler.
If the note interrupted an incomplete system call,
that call returns an error (with error string
interrupted)
after the process resumes.
A notification handler can also jump out to an environment
set up with
setjmp
using the
notejmp
function (see
setjmp(2)),
which is implemented by modifying the saved state and calling
noted(NCONT).
Regardless of the origin of the note or the presence of a handler,
if the process is being debugged
(see
proc(3))
the arrival of a note puts the process in the
Stopped
state and awakens the debugger.
Atnotify
Rather than using the system calls
notify
and
noted,
most programs should use
atnotify
to register notification handlers.
The parameter
in
is non-zero to register the function
f,
and zero to cancel registration.
A handler must return a non-zero number
if the note was recognized (and resolved);
otherwise it must return zero.
When the system posts a note to the process,
each handler registered with
atnotify
is called with arguments as
described above
until one of the handlers returns non-zero.
Then
noted
is called with argument
NCONT.
If no registered function returns non-zero,
atnotify
calls
noted
with argument
NDFLT.
APE
Noted
has two other possible values for its argument.
NSAVE
returns from the handler and clears the note, enabling the receipt of another,
but does not return to the program.
Instead it starts a new handler with the same stack, stack pointer,
and arguments as the
original, at the address recorded in the program counter of the
Ureg
structure. Typically, the program counter will be overridden by the
first note handler to be the address of a separate function;
NSAVE
is then a ‘trampoline’ to that handler.
That handler may execute
noted(NRSTR)
to return to the original program, usually after restoring the original program
counter.
NRSTR
is identical to
NCONT
except that it can only be executed after an
NSAVE.
NSAVE
and
NRSTR
are designed to improve the emulation of signals by the ANSI C/POSIX
environment; their use elsewhere is discouraged.
Notes
The set of notes a process may receive is system-dependent, but there
is a common set that includes:
Note Meaning
interrupt user interrupt (DEL key)
hangup I/O connection closed
alarm alarm expired
sys: breakpoint breakpoint instruction
sys: bad address system call address argument out of range
sys: odd address system call address argument unaligned
sys: bad sys call system call number out of range
sys: odd stack system call user stack unaligned
sys: write on closed pipe write on closed pipe
sys: fp: fptrap floating point exception
sys: trap: trap other exception (see below)
The notes prefixed
sys:
are generated by the operating system.
They are suffixed by the user program counter in format
pc=0x1234.
If the note is due to a floating point exception, just before the
pc
is the address of the offending instruction in format
fppc=0x1234.
Notes are limited to
ERRLEN
bytes; if they would be longer they are truncated but the
pc
is always reported correctly.
The types and syntax of the
trap
and
fptrap
portions of the notes are machine-dependent.
SOURCE
/sys/src/libc/9syscall
/sys/src/libc/port/atnotify.c
SEE
postnote(2),
intro(2),
notejmp
in
setjmp(2)
BUGS
Since
exec(2)
discards the notification handler, there is a window
of vulnerability to notes in a new process.