views:

166

answers:

3

We have a small daemon application written in C for a couple of various UNIX platforms (this problem is happening in SunOS 5.10), that basically just opens up a serial port and then listens for information to come in via said port.

In this particular instance, the daemon appears to read a single transmission (like a file's worth of data) sent over via the serial port, then it receives a SIGINT. This happens every time. Other customers use this setup very similarly without receiving the SIGINT. Quite obviously, the users are NOT pressing Ctrl-C. We have a relatively simple signal handler in place, so we definitely know that that is what is happening.

What else could possibly be causing this? Googling around and looking through the questions here, I couldn't find much explanation as to other things that could cause a SIGINT. I also looked through the code and found no calls to raise() and only a single call to kill(pid, 0) which wouldn't send a SIGINT anyway.

Any thoughts or insight would definitely be appreciated.

A: 

I found an interesting blog post about debugging a problem with similar symptoms. While I doubt it's the same issue, it's got some very useful debugging tips for tracing the origin of signals.

Dave Rigby
This looks pretty interesting and actually kind of similar to what I'm experiencing. I've made a change that was recommended by the blog post and am currently in the process of testing.
Morinar
+1  A: 

You didn't say how your signal handler is attached, but if you're able to attach it using sigaction(2) so as to get a siginfo_t then it looks like that would include the pid that sent the signal (si_pid).

Chris Boyle
Oops, that link was a Linux man page. A copy of the SunOS 5.10 one is at http://compute.cnr.berkeley.edu/cgi-bin/man-cgi?sigaction+2 (that one doesn't list the members of siginfo_t but hopefully si_pid is still present).
Chris Boyle
It's being attached with signal(), which I've not read is "unfavored." If I don't make any progress, I'll try switching it to sigaction().
Morinar
Whoops, the previous comment should read "which I've read is 'unfavored'. Regardless, looking at the man page, it doesn't look like the si_pid is set for SIGINT. Only the first three fields are set for all signals, the rest are a union which seem to be set in only specific circumstances. Good thought though.
Morinar
+1  A: 

If you do not want the serial port to become the controlling terminal for the process, open it using the open flag O_NOCTTY. If it is the controlling terminal, data from the serial port may be interpreted as an interrupt or other special character.

mark4o
I'm going to accept this as it was the most helpful tip presented in any of the three answers, but the truth was a little bit more interesting. Basically, to mark the completion of a transmission on the serial port, an ETX (ascii char 3) was being sent over. Turns out that this character also doubles as the SIGINT character. The Solaris machine was seeing the character, evaluating it as a signal and then passing the signal to the process. The solution was as simple as adding the ISIG c_lflag and setting it with ioctl(). I did set O_NOCTTY too, as it should have been that way anyway.
Morinar
BTW: the ISIG flag basically just turns off signal process on the serial port... basically a must if you are reading in RAW mode like I was.
Morinar
Good reference for anybody who has a similar issue in the future: http://www.easysw.com/~mike/serial/serial.html
Morinar