Hardware signals, PtAppAddSignalProc(), program lockup

ABSTRACT
Hardware-generated signals SIGFPE and SIGSEGV result in program lockup

when Photon signal handlers have been defined for these signals using
PtAppAddSignalProc().

DETAILS
The App: A Photon app that uses PtAppAddSignalProc() to add a handler for

several signals, including the “hardware-generated” signals SIGFPE and
SIGSEGV.
The app has a debug menu that allows me to cause these signals to be
raised –
e.g., division by zero, null pointer assignment.

The Problem: When a hardware-generated error occurs, the app locks up. It
never
gets to my signal handler. The debugger never returns from the ‘int 0F2’
assembler
instruction. Running ‘sin -P myapp sig’ multiple times shows the pending
signal and
mask for the app continually changing – for example:

SIG MASK SIG PEND
00000000 00000080 // pending
00000080 00000000 // masked
00000000 00000000 // clear
00000080 00000000 // masked
00000000 00000080 // pending

What Works: The signal handler does what it is supposed to do when I send it
signals externally using ‘slay’, or internally using raise() or kill(), even
for SIGFPE
and SIGSEGV. If I don’t add a signal handler for SIGFPE and SIGSEGV using
PtAppAddSignalProc(), the program terminates as expected.

What’s Happening?: It looks like the signal keeps being generated. Is it
possible
that the kernel keeps returning to the offending code that caused the error?
This has me baffled.

Dale Sherwood <dsherwoo@nyab.com> wrote:

Hardware-generated signals SIGFPE and SIGSEGV result in program lockup
when Photon signal handlers have been defined for these signals using
PtAppAddSignalProc().

What’s Happening?: It looks like the signal keeps being generated. Is it
possible
that the kernel keeps returning to the offending code that caused the error?
This has me baffled.

The Photon library installs a signal handler that just sets a flag and
returns. At a later point, it checks the flag and invokes your Photon
handler.

This works as expected for asynchronous signals generated by kill() or
slay; but when you get a SIGSEGV, SIGBUS, or SIGFPE because you’re
trying to do something illegal like dereference NULL or divide by zero,
returning from the signal handler brings you back to the opcode that
caused the original signal – and it causes the signal again, and the
handler runs and returns again, and so on.


Wojtek Lerch QNX Software Systems Ltd.

Wojtek Lerch wrote in message <9qptu7$s97$1@nntp.qnx.com>…

Dale Sherwood <> dsherwoo@nyab.com> > wrote:
Hardware-generated signals SIGFPE and SIGSEGV result in program lockup
when Photon signal handlers have been defined for these signals using
PtAppAddSignalProc().

This works as expected for asynchronous signals generated by kill() or
slay; but when you get a SIGSEGV, SIGBUS, or SIGFPE because you’re
trying to do something illegal like dereference NULL or divide by zero,
returning from the signal handler brings you back to the opcode that
caused the original signal – and it causes the signal again, and the
handler runs and returns again, and so on.


Wojtek Lerch QNX Software Systems Ltd.

First – Let me apologize for sending this message multiple times. Each was
a draft that I didn’t expect MS Outlook Express to send. I intended to send
it later after further investigation. Sorry about that.

Second – Thank you! What you say is exactly what I suspected was happening,
but could not really trace in the debugger. I have since discovered that it
also occurs for SIGPIPE, which is presumably not hardware generated. No
doubt this will be a problem for any internally-generated signal.

I assume that this is operating as intended, and is not a bug? That is
probably why I have found no online information about a “fix” for it.
I have a small Photon app that demonstrates the problem, if you are
interested.

How would you go about logging a signal to a file before terminating the
app? I thought that was what PtAppAddSignalProc() was going to allow me
do – instead, it appears to be useful only for IPC signals such as SIGUSR1.
According to my docs (Watcom 10.6), all but the most trivial functions are
non-re-entrant, so I cannot do much useful stuff in a normal signal handler.

The Trace…() family of functions might be useful, but this is not without
its own problems: (a) my QNX 4 Course Notes says that my app must be
privileged and run as root; (b) the trace buffer is apparently not
persistent; (c) proper use requires “code” assignment from QNX SSL.
I suppose I could cron a task to periodically dump the trace buffer to a
file, but I’d rather not run my app as root.

Maybe a better choice is syslog(). There are at least two problems with
this: (a) it does not appear to be signal-safe; (b) I cannot find it in any
libraries on my development system.

->>>–Dale Sherwood–> New York Air Brake Corp., TDS Group

Dale Sherwood <dsherwoo@nyab.com> wrote:

Second – Thank you! What you say is exactly what I suspected was happening,
but could not really trace in the debugger. I have since discovered that it
also occurs for SIGPIPE, which is presumably not hardware generated. No
doubt this will be a problem for any internally-generated signal.

I wouldn’t expect it to happen with SIGPIPE, unless your code keeps
retrying the interrupted write() call.

I assume that this is operating as intended, and is not a bug? That is
probably why I have found no online information about a “fix” for it.
I have a small Photon app that demonstrates the problem, if you are
interested.

If it locks up without returning from the write() call that generates
the SIGPIPE, then I’m interested.

How would you go about logging a signal to a file before terminating the
app? I thought that was what PtAppAddSignalProc() was going to allow me
do – instead, it appears to be useful only for IPC signals such as SIGUSR1.
According to my docs (Watcom 10.6), all but the most trivial functions are
non-re-entrant, so I cannot do much useful stuff in a normal signal handler.

It’s safe to call open(), write(), and close() in a signal handler.

\

Wojtek Lerch QNX Software Systems Ltd.