EXIT_FAILURE vs EXIT_SUCCESS and its effect on devc-ser8250

Hi,

I have written a process that is using a serial device that is controlled by
devc-ser8250 and I came across something that seems quite odd. If the
program exits due to a kill signal or an exit(EXIT_SUCCESS) and starts up
again everything will be fine. However, if it exits with an
exit(EXIT_FAILURE), the next time my program is run it will not write
correctly to the serial port until devc-ser8250 is slayed and restarted. For
example, when it starts it will want to write a 14 character string (that
starts with 0x01) to the serial port. If my program starts after an
exit_failure it will only write one byte (0x11) to the serial port.

Thanks
Brent Tweddle
betweddl@warg.uwaterloo.ca

betweddl <betweddl@warg.uwaterloo.ca> wrote:

Hi,

I have written a process that is using a serial device that is controlled by
devc-ser8250 and I came across something that seems quite odd. If the
program exits due to a kill signal or an exit(EXIT_SUCCESS) and starts up
again everything will be fine. However, if it exits with an
exit(EXIT_FAILURE), the next time my program is run it will not write
correctly to the serial port until devc-ser8250 is slayed and restarted. For
example, when it starts it will want to write a 14 character string (that
starts with 0x01) to the serial port. If my program starts after an
exit_failure it will only write one byte (0x11) to the serial port.

To my knowledge, there should be no difference in the exit behaviour for
closing fds, etc, for exit(EXIT_FAILURE) vs exit(EXIT_SUCCESS) – all that
is different will be the “exit value” (return value kinda) for the program.

What may by worth doing, is to do an “stty -a < /dev/ser1” (or /dev/ser2,
or whatever port you’re actually opening) after the two different exit
modes, and compare the listed states of the serial port in the two cases,
especially focussing on any sort of flow-control settings.

What I think is likely happening is that your program is leaving the
serial port in a different state on the two different paths through
it.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

Hi,

Here’s a bit more info:

What I am doing is writing a program to interface with a GPS over a serial
port. I am letting
the program run and then pulling out the D connector on the back of the
machine - the program
should timeout with a readcond() and then exit with a failure mode. However
if I compile the code
with EXIT_FAILURE as the status bit, when I restart the program it will not
send the proper message
to initialize the GPS. If I recompile it with EXIT_SUCCESS everything works
fine.

So it is not even a different path of execution that is setting things,
unless the exit status effects what happens
in other calls like close() that were called before exit(), which I doubt.

As for stty -a < /dev/ser1, the only change I noticed in any situation was a
difference in baud rate, which is
done by the GPS program.

Thanks,
Brent Tweddle
Waterloo Aerial Robotics Group

“David Gibbs” <dagibbs@qnx.com> wrote in message
news:d8k9na$s3e$1@inn.qnx.com

betweddl <> betweddl@warg.uwaterloo.ca> > wrote:
Hi,

I have written a process that is using a serial device that is controlled
by
devc-ser8250 and I came across something that seems quite odd. If the
program exits due to a kill signal or an exit(EXIT_SUCCESS) and starts up
again everything will be fine. However, if it exits with an
exit(EXIT_FAILURE), the next time my program is run it will not write
correctly to the serial port until devc-ser8250 is slayed and restarted.
For
example, when it starts it will want to write a 14 character string (that
starts with 0x01) to the serial port. If my program starts after an
exit_failure it will only write one byte (0x11) to the serial port.

To my knowledge, there should be no difference in the exit behaviour for
closing fds, etc, for exit(EXIT_FAILURE) vs exit(EXIT_SUCCESS) – all that
is different will be the “exit value” (return value kinda) for the
program.

What may by worth doing, is to do an “stty -a < /dev/ser1” (or /dev/ser2,
or whatever port you’re actually opening) after the two different exit
modes, and compare the listed states of the serial port in the two cases,
especially focussing on any sort of flow-control settings.

What I think is likely happening is that your program is leaving the
serial port in a different state on the two different paths through
it.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

betweddl <betweddl@warg.uwaterloo.ca> wrote:

Hi,

I looked at the code to exit(), non of the application-side cleanup
it does (atexit handlers, flusshing streams) is any different based
on the status passed in. Eventually, that status gets passed to
a call to ThreadDestroy() [a kernel call] which does the final
destruction of the thread(s) in the process and triggers the
destruction of the process itself. I’ve not tried to trace that
code, but I can’t see the kernel doing anything different based on
that status – it isn’t meaningful at the kernel level, just a value
to be passed around.

Here’s a bit more info:

What I am doing is writing a program to interface with a GPS over a serial
port. I am letting
the program run and then pulling out the D connector on the back of the
machine - the program
should timeout with a readcond() and then exit with a failure mode. However
if I compile the code
with EXIT_FAILURE as the status bit, when I restart the program it will not
send the proper message
to initialize the GPS. If I recompile it with EXIT_SUCCESS everything works
fine.

By this, do you mean you make one and only one single word change, the
word FAILURE to SUCCESS directly in the call to exit()?

So it is not even a different path of execution that is setting things,
unless the exit status effects what happens
in other calls like close() that were called before exit(), which I doubt.

As for stty -a < /dev/ser1, the only change I noticed in any situation was a
difference in baud rate, which is
done by the GPS program.

To me, this suggests a different code path on exiting – either restoring
or not restoring a terminal attribute structure (tcsetattr()/tcgetattr()
type calls) leaving the serial port in a different state.

Hm… are you running the program the same way both times? That is,
is it launched on the serial port in an identical manner?

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

Thanks for looking into this,

I think I have determined that the problem is not exit(). I am able to
create the good and bad
situations with both versions of exit(). However I still do not understand
the problem - I have
traced the same path of execution (through lots of print lines) and been
able to see that it creates both rsults.
stty -a is the same when the devc is broken and when it is not - any ideas??

FYI:

I open the port, set the parameters flush the stream, read and write
multiple bytes, then close the port and exit


Thanks,
Brent

“David Gibbs” <dagibbs@qnx.com> wrote in message
news:d8ksap$bpa$1@inn.qnx.com

betweddl <> betweddl@warg.uwaterloo.ca> > wrote:
Hi,

I looked at the code to exit(), non of the application-side cleanup
it does (atexit handlers, flusshing streams) is any different based
on the status passed in. Eventually, that status gets passed to
a call to ThreadDestroy() [a kernel call] which does the final
destruction of the thread(s) in the process and triggers the
destruction of the process itself. I’ve not tried to trace that
code, but I can’t see the kernel doing anything different based on
that status – it isn’t meaningful at the kernel level, just a value
to be passed around.

Here’s a bit more info:

What I am doing is writing a program to interface with a GPS over a
serial
port. I am letting
the program run and then pulling out the D connector on the back of the
machine - the program
should timeout with a readcond() and then exit with a failure mode.
However
if I compile the code
with EXIT_FAILURE as the status bit, when I restart the program it will
not
send the proper message
to initialize the GPS. If I recompile it with EXIT_SUCCESS everything
works
fine.

By this, do you mean you make one and only one single word change, the
word FAILURE to SUCCESS directly in the call to exit()?

So it is not even a different path of execution that is setting things,
unless the exit status effects what happens
in other calls like close() that were called before exit(), which I
doubt.

As for stty -a < /dev/ser1, the only change I noticed in any situation
was a
difference in baud rate, which is
done by the GPS program.

To me, this suggests a different code path on exiting – either restoring
or not restoring a terminal attribute structure (tcsetattr()/tcgetattr()
type calls) leaving the serial port in a different state.

Hm… are you running the program the same way both times? That is,
is it launched on the serial port in an identical manner?

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

betweddl <betweddl@warg.uwaterloo.ca> wrote:

Thanks for looking into this,

I think I have determined that the problem is not exit().

I didn’t think it was.

I am able to
create the good and bad
situations with both versions of exit(). However I still do not understand
the problem - I have
traced the same path of execution (through lots of print lines) and been
able to see that it creates both rsults.
stty -a is the same when the devc is broken and when it is not - any ideas??

Nothing solid.

The two most likely candidates:

  1. does one path leave the GPS on the other end in a bad state?
  2. does one path leaving terminal/port settings wrong, that don’t
    get properly reset/cleared/established again?

Maybe you could hook up a null-modem cable to another serial port, and
just watch what comes accross, see if you get the correct result.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com

Further info below

-thanks
Brent

“David Gibbs” <dagibbs@qnx.com> wrote in message
news:d8n39b$152$1@inn.qnx.com

The two most likely candidates:

  1. does one path leave the GPS on the other end in a bad state?

Part of the initialization is to reset the GPS which should work no matter
what state it is in.
This works on a windows sample program. As mentioned below I have hooked it
up
to another machine and the qnx box won’t transmit the correct signal. When
its working
it transmits 11 bytes starting with 0x01, as the init command, and I see
that on another terminal. If I then get it into
a “broken” mode and hook it up to another machine and run the program that
tries to send
the initialization command, and it only sends 1 byte 0x11 (there is no
relevance that I can see to the byte 0x11),
and of course gets stuck waiting for a response to the initialization
command.

  1. does one path leaving terminal/port settings wrong, that don’t
    get properly reset/cleared/established again?
    Here is roughly my serial port opening sequence (minus error checking):

//open serial port

sd = open(serPort,O_RDWR/| O_NOCTTY/);

//get serial port attributes

returnValue = tcgetattr(sd, &serial_param);

//change the output speed of the serial port

returnValue = cfsetospeed(&serial_param, BAUD_RATE);

//set the input speed of the serial port

returnValue = cfsetispeed(&serial_param, BAUD_RATE);

//set flags

serial_param.c_cflag |= CS8; //8 bits

serial_param.c_cflag &= ~CSTOPB; //1 stop bit (not 2)

serial_param.c_cflag &= ~PARENB; //no parity checking

//set the newly changed speeds of the serial port

returnValue = tcsetattr(sd,TCSANOW,&serial_param);

returnValue = tcflush(sd,TCIOFLUSH);


return 0;

Is there anything else I can reset on the serial port. In all cases, I call
close(sd)
before I exit, unless of course I send a SIGKILL, but that never seems to
cause problems.

betweddl wrote:

a “broken” mode and hook it up to another machine and run the program that
tries to send the initialization command, and it only sends 1 byte 0x11
(there is no relevance that I can see to the byte 0x11),

Well, 0x11 is an XON character. Is something being flow-controlled? Are
you using s/w or h/w flow control? Has devc-ser* been started forcing a
particular mode (-f/F/s/S)? Do you set it yourself? Look for a “+paged”
setting in the “stty -a” display (or maybe post this).

betweddl <betweddl@warg.uwaterloo.ca> wrote:

Further info below

I’ve looked – I don’t see anything that I recognise as wrong. Nor,
unfortunately do I have anything left to suggest. Maybe someone else
will have some ideas. (At least I think we’re closer to focussing
on the right part of the problem, rather than the exit() call.)

-David


David Gibbs
QNX Training Services
dagibbs@qnx.com

Hi,

There is no flow control - 3 wire serial port and I have not told
software to send any special flow control bytes (i.e. 0x11).

Here is stty -a when it fails:

Name: /dev/ttyp2
Type: pseudo
Opens: 2
-parenb -parodd -parstk -cstopb -inpck +hupcl +cread -clocal +isig
+icanon
+iexten +echo +echoe +echok +echoke -echonl +echoctl -noflsh -ignbrk
+brkint
-ignpar -parmrk -istrip -inlcr -igncr +icrnl +imaxbel +opost +onlcr
-isflow +osflow -ihflow -ohflow
intr=^C quit=^\ erase=^? kill=^U eof=^D eol=^- eol2=^-
swtch=^-
start=^Q stop=^S susp=^Z dsusp=^- reprint=^- discard=^- werase=^-
lnext=^V
min=01 time=00 fwd=^- login=^- pr1=^[ pr2=5B pr3=^-
pr4=^-
sf1=^- sf2=^- sf3=^- sf4=^- left=44 right=43 up=41
down=42
ins=40 del=50 rub=FF can=FF home=48 end=59
par=none bits=8 stopb=1 baud=57600 rows=25,80

This is exactly the same as when the serial port is working fine. I
restart the serial driver by:

slay devc-ser8250
/sbin/devc-ser8250

Thanks for your help

In article <d8o8h9$qh3$1@inn.qnx.com>, betweddl@warg.uwaterloo-dot-
ca.no-spam.invalid says…
[…]

-isflow +osflow -ihflow -ohflow
^^^^^^^^^^^^^^^^^

try -osflow

you don’t need to tell software to send any flow control chars. that’s
what driver for. if you don’t need flow control, disable it. also i
don’t think you need canonical mode.

Sorry, I screwed up and posted the output of stty fro the wrong
terminal. Here is to correct output for when it is broken, which is
the same as when it is working or when it has been reset (minus the
baud rate change). As you can see it is -osflow

-Thanks

Name: /dev/ser1
Type: serial
Opens: 1
+hupcl +cread -clocal -isig -icanon -iexten -echo +echoe -echok
+echoke -echonl
+echoctl -noflsh -ignbrk -brkint -ignpar -parmrk -istrip -inlcr -igncr
-icrnl
+imaxbel -opost +onlcr
-isflow -osflow +ihflow +ohflow
intr=^C quit=^\ erase=^? kill=^U eof=^D eol=^- eol2=^-
swtch=^-
start=^Q stop=^S susp=^Z dsusp=^- reprint=^- discard=^- werase=^-
lnext=^V
min=01 time=00 fwd=^- login=^- pr1=^[ pr2=5B pr3=^-
pr4=^-
sf1=^- sf2=^- sf3=^- sf4=^- left=44 right=43 up=41
down=42
ins=40 del=50 rub=^- can=^- home=48 end=59
par=none bits=8 stopb=1 baud=19200 rows=0,0

betweddl wrote:

Sorry, I screwed up and posted the output of stty fro the wrong
terminal. Here is to correct output for when it is broken, which is
the same as when it is working or when it has been reset (minus the
baud rate change). As you can see it is -osflow

-isflow -osflow +ihflow +ohflow
^^^^^^^^^^^^^^^

But now it is set up for h/w flow control.

Perhaps knock down all the flow control in your serial port setup:

serial_param.c_iflag &= ~(IXON | IXOFF);
serial_param.c_cflag &= ~(IHFLOW | OHFLOW);

Or get a “null modem”-style cable with RTS/CTS and DTR/CD shorted :wink:

Hi,

Looks like that worked! Thanks a lot everyone.

I’m still somewhat confused as to why this occurred only when I pulled
the dconnector out of the serial port while the program was running.
FYI: none of the flow control lines are connected to anything - the
tx, rx and gnd all go to a breadboard - nothing else.

Thanks


John Garveywrote:
betweddl wrote:
Sorry, I screwed up and posted the output of stty fro the wrong
terminal. Here is to correct output for when it is broken, which is
the same as when it is working or when it has been reset (minus the
baud rate change). As you can see it is -osflow

-isflow -osflow +ihflow +ohflow
^^^^^^^^^^^^^^^
But now it is set up for h/w flow control.

Perhaps knock down all the flow control in your serial port setup:

serial_param.c_iflag &= ~(IXON | IXOFF);
serial_param.c_cflag &= ~(IHFLOW | OHFLOW);

Or get a “null modem”-style cable with RTS/CTS and DTR/CD shorted
:wink:[/quote:b10d35d82f]

betweddl <betweddl@warg.uwaterloo-dot-ca.no-spam.invalid> wrote:

Hi,

Looks like that worked! Thanks a lot everyone.

I’m still somewhat confused as to why this occurred only when I pulled
the dconnector out of the serial port while the program was running.

It is quite possible to get “odd” voltages/currents during a disconnect
while there is activity that could leave the uart in an unexpected
state.

-David

David Gibbs
QNX Training Services
dagibbs@qnx.com