[comp.unix.wizards] Shell scripts - getting parent status in read

dce@Solbourne.COM (David Elliott) (04/23/89)

I have an interesting problem.  I have a program that runs attached to
the terminal, and it runs shell scripts underneath.  The shell script
and the parent communicate via pipes, and the most common situation is
for the shell script to be executing a "read" command, waiting for the
parent to send down a response (usually as a result of the user
typing).

I have things set up such that if the shell script quits, the parent
knows this and quits, and if the parent quits gracefully, it tells the
shell script to quit as well.

The problem case is where the parent doesn't terminate gracefully, such
as when it dumps core or when I quit from under the debugger.  In this
case, the shell script just sits in read forever.

Is there a way for the shell script to detect that this has happened
and quit?  Obviously, this is out of the realm of a SIGPIPE trap, since
that means that you are writing to a pipe with no one to read it, and I
know of no SIGPARENT.

One idea I came up with was to change the read loop to something like

	checkparent()
	{
		if kill -0 "$PPID" 2>/dev/null
		then
			(sleep 30 ; kill -12 $$) &
			return
		fi
		exit 1
	}

	while
		...
		trap "checkparent" 12
		(sleep 30 ; kill -12 $$) &
		read event
		trap "" 12
	do
		...
	done

Basically, this traps for signal 12 (which is SIGSYS; I chose it
because it's not likely in this case) and fires off a process to sleep
for a while and then "spring" the trap.  The function "checkparent"
checks to see if the parent process (whose id can be passed to the
shell script) is still alive, and if not forces the shell script to
exit.  If the parent is alive, it resets the trap and returns so that
the read can complete.

Can anyone think of an easier method for checking this, or a way to
have the shell script just killed when the parent goes away?

-- 
David Elliott		dce@Solbourne.COM
			...!{boulder,nbires,sun}!stan!dce

bill@twwells.uucp (T. William Wells) (04/23/89)

Try enabling SIGPIPE in your parent before calling the shell script.
When the parent dies, the children trying to read from pipes set up
by the parent should then get a signal. You might have to use a trap
command in the shells, though.

---
Bill                            { uunet | novavax } !twwells!bill

dce@Solbourne.COM (David Elliott) (04/24/89)

In article <849@twwells.uucp> bill@twwells.UUCP (T. William Wells) writes:
>Try enabling SIGPIPE in your parent before calling the shell script.
>When the parent dies, the children trying to read from pipes set up
>by the parent should then get a signal. You might have to use a trap
>command in the shells, though.

Are you sure about this?

SIGPIPE *is* "enabled" in the parent (I just checked).  Generally,
when you execute a program interactively, all signals are set to
SIG_DFL.  Also, SIGPIPE is not a special case, so the default for
it is to cause the program to terminate.

In any case, SIGPIPE means that an attempt was made to write on a
pipe with noone to read it, and that's not what is happening here
(I did say that in the original note, I think).  This is a situation
where a read is being attempted on a pipe with noone on the other
side.  I would think this would cause an EOF, and there was some
discussion on this recently, but it doesn't.

-- 
David Elliott		dce@Solbourne.COM
			...!{boulder,nbires,sun}!stan!dce

ka@june.cs.washington.edu (Kenneth Almquist) (04/26/89)

dce@Solbourne.COM (David Elliott) writes:
> [A] read is being attempted on a pipe with [no one] on the other
> side.  I would think this would cause an EOF, and there was some
> discussion on this recently, but it doesn't.

It does cause an EOF, unless your UNIX is broken (which is unlikely).
Probably you are forgetting to close the other end of the pipe.  The
way to set up a pipe to a child process (exclusive of error checking) is:

	pipe(pip);
	if (fork() == 0) {
-->		close(pip[1]);
		runchild(pip[0]);
		exit(0);
	}
	close(pip[0]);
	...

If you leave out the line that I've marked with an arrow, the child
process will have both ends of the pipe open, so even when the parent
terminates the child still won't get an EOF when it reads from the
pipe.
				Kenneth Almquist

bill@twwells.uucp (T. William Wells) (04/26/89)

In article <866@marvin.Solbourne.COM> dce@Solbourne.com (David Elliott) writes:
: In article <849@twwells.uucp> bill@twwells.UUCP (T. William Wells) writes:
: >[something stupid].
:
: Are you sure about this?

No. I have no idea what drugs I had been slipped when I wrote that. Or
maybe it's lack of sleep? :-)

:        I would think this would cause an EOF, and there was some
: discussion on this recently, but it doesn't.

So would I. And, in fact it does. The problem is that the shell
doesn't exit on EOF. I just tested this on my V/386 3.0 Bourne shell.

I wrote a little shell:

	while true
	do
		read foo
		echo "<$foo>"
	done

to see what happens. And what happens is that EOF and newline both
set foo to a null string.

HEY! I just RTFM. According to it, you get a return status from read!
Adding:

		echo $?

before the other echo, I get 0 on a blank line, 1 on EOF.

When I feed data through a pipe, it works as expected.

(I feel better now I can wipe the egg off my face.)

---
Bill                            { uunet | novavax } !twwells!bill

dce@Solbourne.COM (David Elliott) (04/27/89)

Thanks to all who responded.

It was indeed a case of me not closing the other ends of the
pipes in the child.  I now get an EOF as expected.

-- 
David Elliott		dce@Solbourne.COM
			...!{boulder,nbires,sun}!stan!dce

steve@nuchat.UUCP (Steve Nuchia) (04/28/89)

In article <869@twwells.uucp> bill@twwells.UUCP (T. William Wells) writes:
>	while true
>	do
>		read foo
>		echo "<$foo>"
>	done

>to see what happens. And what happens is that EOF and newline both
>set foo to a null string.

Try this one:

	while read foo
	do
		echo $foo
	done

-- 
Steve Nuchia	      South Coast Computing Services
uunet!nuchat!steve    POB 890952  Houston, Texas  77289
(713) 964 2462	      Consultation & Systems, Support for PD Software.