Skip to content. | Skip to navigation

Navigation

You are here: Home / Support / Guides / Porting / Error and Signal Names

Personal tools

Error and Signal Names

Exyz and SIGabc

*nix manual pages refer to system call error numbers such as EINTR and EBADF and signals are usually referred to as SIGINT and SIGSEGV etc..

But curiously, there's nothing in libc to print those strings out. There are macros/constants that define the values but no associated strings.

strerror(3) and strsignal(3) return helpful strings such as No child processes for ECHILD and Interrupt for SIGINT. If we want the strings ECHILD and SIGINT then we have to concoct our own scheme.

Bash does this for signals in support/signames.c but nothing for errno.

The broad thrust of Bash's approach is to create an array of char * and allocate a fixed-length string (big enough for the largest name) for each then plod through all known signal names (across all OS') with:

#if defined(SIGHUP)
    sprintf (array[SIGHUP], "SIGHUP");
#endif

Signals

With the design above all we need to know is how many signals there are? Yes? Almost. There's a complication with signals in that if realtime signals are defined (SIGRTMIN through SIGRTMAX) then they are not necessarily adjacent to the "regular" signals.

Range

Everyone agrees we should start at 1 with SIGHUP. Hooray!

Almost everyone agrees that regular signals should end at NSIG.

FreeBSD doesn't. To it, NSIG is the "number of old signals" and all we can really do is define the end of the array as SIGRTMAX + 1.

Note

In the Bash sources they get upset with AIX as the realtime signals are nowhere near adjacent to the number of the other signals (hundreds away). I don't have an AIX box so I can't comment.

#if defined (BSD)
#define LAST_SIG (SIGRTMAX + 1)
#else
#define LAST_SIG NSIG
#endif
Realtime Signals

The set of realtime signal names is: SIGRTMIN, SIGRTMIN+1, SIGRTMIN+2, ..., SIGRTMAX-2, SIGRTMAX-1, SIGRTMAX. If there is an odd number, then the extra one in the middle is SIGRTMIN+n for some n.

So, as long as we do some careful counting, that's pretty straight-forward.

Linux

Linux throws a subtle spanner in the works. If you grovel around in the header files, asm-generic/signal.h defines SIGRTMIN as 32.

However, the comment against it says:

These should not be considered constants from userland.

When you compile your code, SIGRTMIN comes out as 34 -- and appears to be defined as (__libc_current_sigrtmin ()) in bits/signum.h.

This should not affect your code but it may impact on your (read: my) expectations.

Length

Suppose we set the nominal signal name length to be 14 characters which seems plenty long enough.

As a side-effect, the maximum n in SIGRTMIN+n is 9999 -- as SIGRTMIN+ is 9 characters and we need a \0 leaving four characters for n. 9999 realtime signals should covers us, I think.

Any gap would be filled with SIGJUNKn.

Errors

Errors are slightly easier than signals although the same principle applies.

Linux's errno(3) indicates it uses the set from POSIX.1 and C99 and that EAGAIN and EWOULDBLOCK "may be the same."

Solaris-derived OS' suggest in intro(2) that the set comes from the Single UNIX Specification.

Range

Everyone seems to start at 1.

Only OS X and FreeBSD define ELAST so for the rest we simply have to know what the (current) last error number is:

#if defined (BSD)
#define LAST_ERRNO (ELAST + 1)
#elif defined (__linux__)
#define LAST_ERRNO (EHWPOISON + 1)
#elif defined (__APPLE__) && defined (__MACH__)
#define LAST_ERRNO (ELAST + 1)
#elif defined (__sun) && defined (__SVR4)
#define LAST_ERRNO (ESTALE + 1)
#else
#error Cannot define LAST_ERRNO
#endif

Length

Empirical study suggests the longest errno names are ENOTRECOVERABLE, EPROTONOSUPPORT and ESOCKTNOSUPPORT at 15 characters apiece.

Any gaps would be filled with ERRNOn where it's unlikely that n will be more than 3 characters. Well within the 15 characters above.

Document Actions