Informix Error -4
-4 Interrupted system call.
An operating-system error code with the meaning shown was unexpectedly returned to the database server. You might have pressed the interrupt key at a crucial moment, or the software might have generated an interrupt signal such as the UNIX command kill. Look for other operating-system error messages that might give more information. If the error recurs, note all circumstances and contact IBM Informix Technical Support.
Oninit® Troubleshooting Guidance
This is an operating-system error number, not an Informix diagnosis.
The same errno is returned by many different operations, so on its own it says what the operating system refused, not what Informix was trying to do. Informix will usually have reported a more specific error alongside it — in the message log, in the SQL or ISAM error pair, or in the accompanying assert failure — and that error normally defines the real cause far more precisely than the errno does. Find it before diagnosing from this number alone.
This matters less than it used to. Later versions of the engine trap many of these conditions and report them as specific Informix errors naming the operation, the object and the context, so a bare errno in this range is increasingly a sign of an older version, an unusual code path, or a failure early in startup before the better reporting is available. If you are seeing one on a current version, the more specific error is worth looking for even harder.
Operating-System Meaning
errno 4 is EINTR — Interrupted system call. A blocking system call was interrupted by a signal before it did any work, and returned early rather than completing.
EINTR is different in kind from most errnos on these pages. Nothing is broken. It is part of the normal contract between signals and blocking calls: the kernel delivers the signal, the call returns EINTR, and the caller is expected to retry. Correctly written code does exactly that, and the condition is never seen.
So the useful question is not "what went wrong?" but:
Which signal arrived, who sent it, and why did the code not retry?
On modern systems most handlers are installed with SA_RESTART, which makes the kernel restart the interrupted call automatically. That makes a visible EINTR informative: it usually means either a signal that cannot be restarted from (SIGSTOP/SIGCONT sequences, timers), or a handler installed without SA_RESTART — very often by application code.
What This Means in Informix
First, what this is not. The official text suggests you "might have pressed the interrupt key at a crucial moment". In practice a user interrupting a running statement does not produce -4. It produces -213, Statement interrupted by user — a SQL-layer error returned to the client, and one that does not normally appear in online.log at all.
That distinction is the useful one:
| -213 | -4 | |
|---|---|---|
| Layer | SQL — returned to the client | Operating system — a raw errno |
| Typical origin | The user cancelled a statement | A signal interrupted a blocked system call |
Seen in online.log? |
Normally no | Sometimes, alongside the operation that failed |
| Action needed | None | Find the signal and the missing retry |
So if you are holding a -4, the interrupt-key explanation is almost certainly the wrong lead. Something signalled a process while it was blocked in a system call, and the interesting part is what.
Typical contexts:
- Something sent a signal — a
killfrom an administrator, a watchdog, a job scheduler enforcing a runtime limit, or a shutdown script. - Application timers. An application using
alarm()or aSIGALRM-based timeout will interrupt whatever Informix call is in progress when it fires. - Application signal handlers in ESQL/C and 4GL. This is the important non-obvious case — see below.
- Backup and restore.
ontapeoronbarblocked on a tape or pipe read, interrupted by a signal. - Wrapper scripts. A shell wrapper reaping children can take
SIGCHLDwhile a read is blocked. - NFS soft mounts, where a signal can interrupt an operation that would otherwise block indefinitely.
ESQL/C and 4GL signal handling
An application that installs its own signal handlers can turn signals that were previously invisible into visible EINTR failures, because a handler installed with plain signal() or with sigaction() and no SA_RESTART stops the kernel restarting the interrupted call.
This is worth checking early in any custom ESQL/C or 4GL estate, because the symptom appears in Informix while the cause is in application code that may not have changed recently — a new library, a different compiler default, or a port to another platform can all change the behaviour without the source being touched.
C UDRs must not touch signals at all
In a C UDR the rule is absolute, and stronger than "install handlers carefully":
The database server reserves all operating-system signals for its own use — the virtual processors use signals to communicate with one another. A UDR that uses signals will conflict with that communication. Do not raise, handle, or mask signals within a C UDR.
All three verbs matter, and the last is the one most often overlooked. Installing a handler is the obvious violation, but raise(), kill() against the server's own processes, and any masking via sigprocmask() or pthread_sigmask() are equally prohibited — including a mask set "temporarily" around a critical section and restored afterwards, which still blocks inter-VP communication for its duration.
So if you find signal code of any kind inside a UDR, that is the finding. It is a defect in its own right, not merely a possible source of this error, and the consequences reach the whole virtual processor rather than the calling session.
ESQL/C provides sqlsignal() for coordinating with the library's own signal handling; consult the ESQL/C programmer's manual for the semantics on your version before adding or removing handlers, as the details differ between releases.
Common Causes
- A signal was sent deliberately by a scheduler, watchdog, or administrator enforcing a timeout.
- Application-installed signal handlers without
SA_RESTART, in ESQL/C or 4GL. (In a C UDR, an installed handler is itself the defect — see above.) - An application
SIGALRMtimeout fired while an Informix call was blocked. - Code that does not retry. The condition was always occurring; only the missing retry makes it visible.
- A blocked I/O operation on a slow device — tape, pipe, or NFS — giving a wide window for a signal to land.
- A client process was killed while the server was mid-operation on its behalf.
Diagnostic Checks
First establish which operation was interrupted, and whether the stop was deliberate — a shutdown or a scheduled kill needs no further investigation:
tail -200 "$INFORMIXDIR/tmp/online.log"
onstat -m
If a client statement is involved, check whether you are actually chasing -213 instead. A statement the user cancelled reports -213 to the client and generally leaves nothing in online.log; if that is what happened, there is nothing here to fix.
Identify the signal, which is the single most useful step. Trace the process and watch for delivery:
# Linux — which signals arrive, and what returns EINTR
strace -f -p "$pid" -e trace=signal
strace -f -e trace=read,write,select,poll -p "$pid" 2>&1 | grep EINTR
# Solaris / AIX
truss -f -p "$pid"
truss -f -s all -p "$pid"
Find out who is sending it. On Linux, audit is the reliable route:
auditctl -a always,exit -F arch=b64 -S kill -k sigtrace
ausearch -k sigtrace | tail -40
Otherwise look at the obvious senders:
crontab -l -u "$(id -un)"
systemctl show <unit> -p TimeoutStopSec -p RuntimeMaxSec
ps -ef | grep -Ei 'watchdog|monitor|timeout'
Check whether the application installs handlers. In a source estate this is a quick grep:
grep -rn -E '\bsignal\s*\(|\bsigaction\s*\(|\balarm\s*\(|sqlsignal' /path/to/src
grep -rn 'SA_RESTART' /path/to/src # absence here is the interesting result
For UDR source, the search is wider and any hit is a defect — raising and masking count, not just handling:
grep -rn -E '\bsignal\s*\(|\bsigaction\s*\(|\braise\s*\(|\bkill\s*\(|\balarm\s*\(' /path/to/udr/src
grep -rn -E 'sigprocmask|pthread_sigmask|sigsuspend|sigwait' /path/to/udr/src
For 4GL and ESQL/C binaries where source is not to hand:
strings /path/to/binary | grep -iE 'sigaction|sqlsignal|alarm'
If a slow device is involved, establish how long calls are actually blocking:
strace -f -T -p "$pid" 2>&1 | sort -t'<' -k2 -rn | head
onstat -g iof
Solutions / Resolution
- Confirm you are on the right error. If a user cancelled a statement, the error is -213 and nothing needs fixing. A deliberate shutdown or scheduled kill likewise needs no action beyond recognising it.
- Retry the call. Where the code is yours, this is the correct handling —
EINTRmeans "nothing happened, try again", not "the operation failed":do { n = read(fd, buf, len); } while (n < 0 && errno == EINTR); - Install handlers with
SA_RESTARTwhere a handler is genuinely needed, so blocking calls restart transparently. - Reconsider the handler entirely. In ESQL/C and 4GL, prefer the library's own facilities over hand-installed handlers, and check
sqlsignal()semantics for your version before changing anything. - Move application timeouts out of signals where possible — a
SIGALRMfiring mid-query is a blunt instrument, and a query-level or connection-level timeout is usually a better fit. - Address the slow device if the interruptions cluster around tape, pipe or NFS I/O. The signal is opportunistic; the long block is what gives it the opportunity.
- Check scheduler limits —
RuntimeMaxSec, job-scheduler kill timers and similar will signal long-running work on a timer, which looks random until you match the timing.
Examples
A scheduler enforcing a runtime limit
A nightly job fails at the same elapsed time every run:
$ systemctl show ifx-nightly -p RuntimeMaxSec
RuntimeMaxSec=1800
Thirty minutes in, systemd signals the unit and whatever Informix call was blocked returns EINTR. The error is a consequence of the limit, not of anything in the database. Either raise the limit or make the job finish inside it.
An application handler without SA_RESTART
An ESQL/C program that began reporting -4 after a rebuild:
$ grep -rn 'signal(' src/
src/daemon.c:142: signal(SIGCHLD, reap_children);
$ grep -rn 'SA_RESTART' src/
$
A SIGCHLD handler installed with plain signal(). Every time a child exits, any blocked Informix call in the parent returns EINTR. Nothing in the SQL or the server changed; the application's process handling did.
Platform Note
errno 4 is EINTR on Linux, AIX, Solaris, HP-UX and the BSD-derived systems — stable, so the number is reliable.
What is not portable is restart behaviour, and this matters more than usual here. Historically, System V signal() did not restart interrupted calls while BSD signal() did, and modern platforms differ in which calls are restartable even with SA_RESTART set — notably for timeouts on sockets and for slow devices. Code ported between platforms can therefore start reporting -4 without changing, which is a common presentation during migrations.
If you are chasing this across platforms, verify the behaviour on the target rather than assuming, and prefer explicit sigaction() with SA_RESTART over signal(), whose semantics are the ones that vary.
Related Errors / Related Topics
- -213 — Statement interrupted by user. What a cancelled statement actually reports. If a user pressed the interrupt key, that is the error to read, not this one.
- -3 — No such process. The other common outcome around signal handling, and often seen in the same scripts.
- -1 — Operation not permitted, when the signal could not be sent at all.
- -32 — Broken pipe, the other error that typically means "something at the other end went away", frequently appearing alongside -4 when a client is cancelled or killed.