| .TH NOTIFY 3 |
| .SH NAME |
| notify, noted, atnotify \- handle asynchronous process notification |
| .SH SYNOPSIS |
| .B #include <u.h> |
| .br |
| .B #include <libc.h> |
| .PP |
| .B |
| int notify(void (*f)(void*, char*)) |
| .PP |
| .B |
| int noted(int v) |
| .PP |
| .B |
| int atnotify(int (*f)(void*, char*), int in) |
| .SH DESCRIPTION |
| When a process raises an exceptional condition such as dividing by zero |
| or writing on a closed pipe, a |
| .I note |
| is posted to communicate the exception. |
| A note may also be posted by a |
| .I write |
| (see |
| .IR read (3)) |
| to the process's |
| .BI /proc/ n /note |
| file or to the |
| .BI /proc/ m /notepg |
| file of a process in the same process group (see |
| .IR 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 |
| \fL"suicide: "\fP, |
| is printed on the process's standard error file |
| and the |
| process is suspended in the |
| .B Broken |
| state for debugging. |
| .PP |
| These default actions may be overridden. |
| The |
| .I notify |
| function registers a |
| .I "notification handler |
| to be called within the process when a note is received. |
| The argument to |
| .I notify |
| replaces the previous handler, if any. |
| An argument of zero cancels a previous handler, |
| restoring the default action. |
| A |
| .IR fork (3) |
| system call leaves the handler registered in |
| both the parent and the child; |
| .IR exec (3) |
| restores the default behavior. |
| Handlers may not perform floating point operations. |
| .PP |
| After a note is posted, |
| the handler is called with two arguments: |
| the first is a pointer to a |
| .B Ureg |
| structure (defined in |
| .BR /$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 |
| .L ERRLEN |
| characters in it including the terminal NUL. |
| The |
| .B 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. |
| .PP |
| A notification handler must finish either by exiting the program or by calling |
| .IR noted ; |
| if the handler returns the behavior |
| is undefined and probably erroneous. |
| Until the program calls |
| .IR noted , |
| any further externally-generated notes |
| (e.g., |
| .B hangup |
| or |
| .BR 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 |
| .I noted |
| defines the action to take: |
| .B NDFLT |
| instructs the system to perform the default action |
| as if the handler had never been registered; |
| .B NCONT |
| instructs the system to resume the process |
| at the point it was notified. |
| In neither case does |
| .I noted |
| return to the handler. |
| If the note interrupted an incomplete system call, |
| that call returns an error (with error string |
| .BR interrupted ) |
| after the process resumes. |
| A notification handler can also jump out to an environment |
| set up with |
| .I setjmp |
| using the |
| .I notejmp |
| function (see |
| .IR setjmp (3)), |
| which is implemented by modifying the saved state and calling |
| .BR noted(NCONT) . |
| .PP |
| Regardless of the origin of the note or the presence of a handler, |
| if the process is being debugged |
| (see |
| .IR proc (3)) |
| the arrival of a note puts the process in the |
| .B Stopped |
| state and awakens the debugger. |
| .PP |
| Rather than using the system calls |
| .I notify |
| and |
| .IR noted , |
| most programs should use |
| .I atnotify |
| to register notification handlers. |
| The parameter |
| .I in |
| is non-zero to register the function |
| .IR 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 |
| .I atnotify |
| is called with arguments as |
| described above |
| until one of the handlers returns non-zero. |
| Then |
| .I noted |
| is called with argument |
| .BR NCONT . |
| If no registered function returns non-zero, |
| .I atnotify |
| calls |
| .I noted |
| with argument |
| .BR NDFLT . |
| .PP |
| .I Noted |
| has two other possible values for its argument. |
| .B 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 |
| .B Ureg |
| structure. Typically, the program counter will be overridden by the |
| first note handler to be the address of a separate function; |
| .B NSAVE |
| is then a `trampoline' to that handler. |
| That handler may executed |
| .B noted(NRSTR) |
| to return to the original program, usually after restoring the original program |
| counter. |
| .B NRSTR |
| is identical to |
| .BR NCONT |
| except that it can only be executed after an |
| .BR NSAVE . |
| .B NSAVE |
| and |
| .B NRSTR |
| are designed to improve the emulation of signals by the ANSI C/POSIX |
| environment; their use elsewhere is discouraged. |
| .PP |
| The set of notes a process may receive is system-dependent, but there |
| is a common set that includes: |
| .PP |
| .RS 3n |
| .nf |
| .ta \w'\fLsys: write on closed pipe \fP'u |
| \fINote\fP \fIMeaning\fP |
| \fLinterrupt\fP user interrupt (DEL key) |
| \fLhangup\fP I/O connection closed |
| \fLalarm\fP alarm expired |
| \fLsys: breakpoint\fP breakpoint instruction |
| \fLsys: bad address\fP system call address argument out of range |
| \fLsys: odd address\fP system call address argument unaligned |
| \fLsys: bad sys call\fP system call number out of range |
| \fLsys: odd stack\fP system call user stack unaligned |
| \fLsys: write on closed pipe\fP write on closed pipe |
| \fLsys: fp: \fIfptrap\f1 floating point exception |
| \fLsys: trap: \fItrap\f1 other exception (see below) |
| .fi |
| .RE |
| .PP |
| The notes prefixed |
| .B sys: |
| are generated by the operating system. |
| They are suffixed by the user program counter in format |
| .BR pc=0x1234 . |
| If the note is due to a floating point exception, just before the |
| .BR pc |
| is the address of the offending instruction in format |
| .BR fppc=0x1234 . |
| Notes are limited to |
| .B ERRLEN |
| bytes; if they would be longer they are truncated but the |
| .B pc |
| is always reported correctly. |
| .PP |
| The types and syntax of the |
| .I trap |
| and |
| .I fptrap |
| portions of the notes are machine-dependent. |
| .SH SOURCE |
| .B /sys/src/libc/9syscall |
| .br |
| .B /sys/src/libc/port/atnotify.c |
| .SH SEE ALSO |
| .IR intro (3), |
| .I notejmp |
| in |
| .IR setjmp (3) |
| .SH BUGS |
| Since |
| .IR exec (3) |
| discards the notification handler, there is a window |
| of vulnerability to notes in a new process. |