Click to See Complete Forum and Search --> : After calling setsid(), why does my child control my parent's terminal??


registering
06-15-2003, 06:42 PM
Hello all,

I have a problem where my application creates a child before doing anything else and the child resets
terminal settings so it can control a serial device in raw mode. Now, what happens is when my parent
dies, the shell terminal settings are in raw mode, as if the PARENT had reset the settings, or as if
the CHILD reset the parent's terminal!

I have the parent calling setsid, and it does not return error, which I believe means the child has
no controlling terminal. The child then continues to change the terminal settings, control the serial
device, and live happily ever after. However meanwhile in the parent's shell, it's in raw mode which
is ugly, so they must always type "reset", which is not very nice.

My parent does nothing but fork(), make sure no errors occurred, then sleep(1) and return (1).

The problem seems to stem from a mystery I discovered in Linux that might be a UNIX thing, I dunno, but
I found the only way to get my serial port settings correct was to set them, then do this:


tcgetattr(1,&port->ser_old_stdout_tio); // we gotta do this - there is a Linux bug
tcsetattr(1,TCSANOW,&port->ser_newtio); // make stdout settings like serial port settings
tcgetattr(0,&port->ser_oldstdtio); // get stdin settings for restoration ...
tcgetattr(0,&port->ser_newstdtio); // ... and use them as a basis for changes
tcsetattr(0,TCSANOW,&port->ser_newstdtio); // set the new attributes immediately



Now why would the above mess-up the parent's stdin/stdout? If I remove this code the port isn't set-up
properly, but if I keep it in, whoever starts my program must type "reset" after executing it, or the
parent can do a "system("reset");" but there must be a better way. Maybe I misunderstand who controls
whose terminal? I open the serial port in O_NOCTTY and I thought setsid gaurantees the child has no
controlling terminal....

Any ideas?

registering
06-16-2003, 07:55 AM
It seems that I need to create two children. The first child after calling setsid() is supposed to get rid of the controlling terminal, but I don't think it does. However creating a second child and letting the first die, then closing stdin, stdout and stderr that I inherited, seems to fix the problem. I'm still not sure why you have to even mess with stdin/stdout to get serial devices working under Linux, though.

Stuka
06-16-2003, 10:09 AM
Not sure about all the issues, but I do know that a child inherits all open file descriptors from its parent, including stdin, stdout, and stderr (which you obviously know) - calling setsid() shouldn't change that at all. Did you try closing the stdXXX file descriptors in the lone child first?

registering
06-18-2003, 10:21 AM
Thanks Stuka. I wasn't closing them in the first child. Doing so solved my problem. However I should probably reopen them in the last child, just for completeness' sake. Plus, it would let me run my program as a daemon and still be able to printf for debugging. Thank again.

Stuka
06-18-2003, 10:28 AM
Happy to help - by the way, for the best (IMO) reference on all sorts of IPC/forking issues, check out "Unix Network Programming, Vol. 2" by W. Richard Stevens - AWESOME stuff.