ericb@libdev.dartmouth.edu (Eric Bivona) (09/06/89)
I have run across a situation that strikes me as a kernel bug, but
maybe I'm just missing something. Here's the problem:
I am responsible for a library of code that does (in part) a fork and
exec to run a DBMS as an inferior process. For various reasons, after
the fork (vfork), the child code runs through the basic disassociate
from control terminal code from the 4.3 BSD Advanced IPC Tutorial. No
problem yet, everything is fine.
A program that uses this library is often run out of a shell script
that may run for *many* hours, preferably at night. If the shell
script is started, and the user logs out, the previously mentioned
program hangs in the previously mentioned library, in the disassociate
code, namely:
if ((fd = open("/dev/tty", O_RDWR | O_NDELAY)) >= 0) {
(void) ioctl(fd, TIOCNOTTY, 0);
(void) close(fd);
}
The open call hangs, waiting for someone connect to the unused tty
port. Since this in the kernel, it is time to get more specific:
4.3 BSD on a VAX 780, and a dz for the ports we're seeing this problem
on (haven't tried on other ports, pty's would be the only other thing
I could easily test this against). I've looked through the code and I
can see (I think) what isn't happening: the dz code does nothing
about the O_NDELAY, and the open blocks, until *anyone* logs into the
port that was used by the person running the script. Maybe somebody
out there is saying: wait, the open is of "/dev/tty", and that's
special, what does it matter with the dz code? Well, if I follow this
correctly (no, I'm not going to bet on it), the special code used for
/dev/tty is in tty_tty.c, and it just calls the open routine for the
user's tty device, with the tty device from the user (kernel)
structure.
I figure the solutions run something like this:
1) fix the dz code to return EWOULDBLOCK, given O_NDELAY, and an
unopened tty. Certainly this would be correct, but it is not
general: every tty handler would have to be correct (it would be
nice, but ...).
2) have the logout propagate an empty tty field to the user structure:
this should occur (I'd guess), or is it overkill of sorts? I
haven't dug deep enough to figure this out.
3) change the /dev/tty code to do the 'right' thing if there is
currently no control terminal. (anyone want to define 'right' as
used in the previous sentence? :->). Might also have to do with
2, above (can you figure out from the u structure if the control
terminal has been disconnected? (there is a comment in this code
about replacing all of it anyway...).
4) Some other solution, hopefully clean, and in user code space that
would fix all this?
Thanks in advance!
-Eric Bivona
DCIS Project
Dartmouth College
Eric.J.Bivona@Dartmouth.EDU
abe@mace.cc.purdue.edu (Vic Abell) (09/07/89)
In article <15412@dartvax.Dartmouth.EDU>, ericb@libdev.dartmouth.edu (Eric Bivona) writes:
about disassociating from a /dev/tty whose control terminal is
no longer open.
I reported this problem to Berkeley some time ago - ca. October, 1988.
My solution is to use a SIGALRM around the open of /dev/tty. It avoids
a kernel hack.
rcodi@chudich.co.rmit.oz (Ian Donaldson) (09/09/89)
abe@mace.cc.purdue.edu (Vic Abell) writes: >In article <15412@dartvax.Dartmouth.EDU>, ericb@libdev.dartmouth.edu (Eric Bivona) writes: > about disassociating from a /dev/tty whose control terminal is > no longer open. >I reported this problem to Berkeley some time ago - ca. October, 1988. >My solution is to use a SIGALRM around the open of /dev/tty. It avoids >a kernel hack. An almost equivalent operation is: setpgrp(0, 0); It has the effect that no signals will be sent to your process anymore from terminals, even though your process is still logically associated with a tty (as far as /bin/ps shows), and it also has the effect that the next tty you open becomes your controlling tty. TIOCNOTTY only has one advantage over this: it removes the association with the original tty. This is rarely noticed. It also has the disadvantage that you noted... blocking if the tty is no longer open by any process (and it waits for carrier). Ian D