Script Hanging

Graham Carpenter graham at brueer.UUCP
Fri May 9 01:52:23 AEST 1986


> We're having a fairly serious problem on our vax used for Instructional
> computing:
> 
> Problem:  Script hangs upon exit with control-d
> 	  It only does so when a process is running in the background
> 	  on the same pty that script was using.
> 
> OS:       Ultrix 1.1
> Machine:  Vax 11/750
> 
> Anyone know what causes this???
> 
> 
> 					-steve

We had a similar problem on a VAX running 4.2BSD. It occurred when a user tried
to run script from a terminal which had been left in an odd state by some other
process - eg someone exiting emacs by killing it.

Those characteristics of the pty which script isn't bothered about are set to be
the same as the user's tty.  If any of these characteristics are at all weird
then CTRL-D will kill the child process which opened the slave pty without
closing the pty properly. Then you are hung!

Sending a SIGCHLD to the parent process doesn't work because the parent only
tests for the closure of the pty. I don't know why SIGCHLD is not a valid way
of telling the parent that the child is done, but I'm no Unix expert (Comments
from a more informed source will be gratefully received!).

Anyway - my fix was to modify the source to script to look for a SIGCHLD <<OR>>
the closure of the pty.

I've included the context diffs to script.c (in shar format to stop the
satellites munging them as they cross the pond!) - hope they are of some help.

I've been using this version for about 6 weeks now with no problems at all.

Graham

/------------------------------------------------------------------------------\
| Graham J Carpenter.            | VOICE: +44 895 74000 Ext 2849               |
| Dept of Electrical Engineering |                                             |
| and Electronics                | ARPA:  graham%ee.brunel.ac.uk at ucl-cs.arpa   |
| Brunel University              |                                             |
| Uxbridge                       | UUCP:  ...!mcvax!ukc!ee.brunel.ac.uk!graham |
| UB8 3PH                        |                                             |
| UNITED KINGDOM                 | JANET: graham at uk.ac.brunel.ee               |
\------------------------------------------------------------------------------/


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	scriptdiff
# This archive created: Thu May  8 10:07:30 1986
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'scriptdiff'" '(4304 characters)'
if test -f 'scriptdiff'
then
	echo shar: "will not over-write existing file 'scriptdiff'"
else
sed 's/^	X//' << \SHAR_EOF > 'scriptdiff'
	X*** script.c	Thu May  8 09:56:26 1986
	X--- script.c.dist	Thu May  8 09:57:33 1986
	X***************
	X*** 4,19
	X  
	X  /*
	X   * script
	X-  * 
	X-  * Modified by Graham Carpenter - Brunel University 9/4/86
	X-  *
	X-  * Make exit condition of child dependent upon EITHER SIGCHLD from grandchild
	X-  * OR closure of channel to psuedo-teletype.
	X-  * 
	X-  * Original script.c only checks closure of pty. This may not always close
	X-  * if pty inherits strange attributes from /dev/tty, leaving shell exited
	X-  * but script not closed. System than hangs. Script cannot then be killed
	X-  * by signals without losing buffered output to script file.
	X   */
	X  
	X  #include <stdio.h>
	X
	X--- 4,9 -----
	X  
	X  /*
	X   * script
	X   */
	X  #include <stdio.h>
	X  #include <signal.h>
	X***************
	X*** 15,21
	X   * but script not closed. System than hangs. Script cannot then be killed
	X   * by signals without losing buffered output to script file.
	X   */
	X- 
	X  #include <stdio.h>
	X  #include <signal.h>
	X  #include <sys/types.h>
	X
	X--- 5,10 -----
	X  /*
	X   * script
	X   */
	X  #include <stdio.h>
	X  #include <signal.h>
	X  #include <sys/types.h>
	X***************
	X*** 31,38
	X  int	master;
	X  int	slave;
	X  int	child;
	X- int	grandchild;
	X- int	sigfrom;
	X  char	*fname = "typescript";
	X  int	finish();
	X  time_t	tvec;
	X
	X--- 20,25 -----
	X  int	master;
	X  int	slave;
	X  int	child;
	X  char	*fname = "typescript";
	X  int	finish();
	X  
	X***************
	X*** 35,41
	X  int	sigfrom;
	X  char	*fname = "typescript";
	X  int	finish();
	X! time_t	tvec;
	X  struct	sgttyb b;
	X  struct	tchars tc;
	X  struct	ltchars lc;
	X
	X--- 22,28 -----
	X  int	child;
	X  char	*fname = "typescript";
	X  int	finish();
	X! 
	X  struct	sgttyb b;
	X  struct	tchars tc;
	X  struct	ltchars lc;
	X***************
	X*** 48,53
	X  	int argc;
	X  	char *argv[];
	X  {
	X  
	X  	shell = getenv("SHELL");
	X  	if (shell == 0)
	X
	X--- 35,41 -----
	X  	int argc;
	X  	char *argv[];
	X  {
	X+ 	int f;
	X  
	X  	shell = getenv("SHELL");
	X  	if (shell == 0)
	X***************
	X*** 84,91
	X  		fail();
	X  	}
	X  	if (child == 0) {
	X! 		grandchild = fork();
	X! 		if (grandchild < 0) {
	X  			perror("fork");
	X  			fail();
	X  		}
	X
	X--- 72,79 -----
	X  		fail();
	X  	}
	X  	if (child == 0) {
	X! 		f = fork();
	X! 		if (f < 0) {
	X  			perror("fork");
	X  			fail();
	X  		}
	X***************
	X*** 89,95
	X  			perror("fork");
	X  			fail();
	X  		}
	X! 		if (grandchild)
	X  			dooutput();
	X  		else
	X  			doshell();
	X
	X--- 77,83 -----
	X  			perror("fork");
	X  			fail();
	X  		}
	X! 		if (f)
	X  			dooutput();
	X  		else
	X  			doshell();
	X***************
	X*** 110,116
	X  
	X  #include <sys/wait.h>
	X  
	X- 
	X  finish()
	X  {
	X  	union wait status;
	X
	X--- 98,103 -----
	X  
	X  #include <sys/wait.h>
	X  
	X  finish()
	X  {
	X  	union wait status;
	X***************
	X*** 115,125
	X  {
	X  	union wait status;
	X  
	X! 	if ((sigfrom = wait3(&status, WNOHANG, 0)) == child)
	X! 		done();
	X! 	else if (sigfrom == grandchild)
	X! 		donechild();
	X! 	else
	X  		return;
	X  }
	X  
	X
	X--- 102,108 -----
	X  {
	X  	union wait status;
	X  
	X! 	if (wait3(&status, WNOHANG, 0) != child)
	X  		return;
	X  	done();
	X  }
	X***************
	X*** 121,126
	X  		donechild();
	X  	else
	X  		return;
	X  }
	X  
	X  dooutput()
	X
	X--- 104,110 -----
	X  
	X  	if (wait3(&status, WNOHANG, 0) != child)
	X  		return;
	X+ 	done();
	X  }
	X  
	X  dooutput()
	X***************
	X*** 125,130
	X  
	X  dooutput()
	X  {
	X  	char obuf[BUFSIZ];
	X  	int cc;
	X  
	X
	X--- 109,115 -----
	X  
	X  dooutput()
	X  {
	X+ 	time_t tvec;
	X  	char obuf[BUFSIZ];
	X  	int cc;
	X  
	X***************
	X*** 138,144
	X  		(void) write(1, obuf, cc);
	X  		(void) fwrite(obuf, 1, cc, fscript);
	X  	}
	X! 		donechild();
	X  }
	X  
	X  doshell()
	X
	X--- 123,133 -----
	X  		(void) write(1, obuf, cc);
	X  		(void) fwrite(obuf, 1, cc, fscript);
	X  	}
	X! 	tvec = time((time_t *)0);
	X! 	fprintf(fscript,"\nscript done on %s", ctime(&tvec));
	X! 	(void) fclose(fscript);
	X! 	(void) close(master);
	X! 	exit(0);
	X  }
	X  
	X  doshell()
	X***************
	X*** 183,206
	X  {
	X  
	X  	ioctl(0, TIOCSETP, (char *)&b);
	X! 	printf("\nScript done, file is %s\n", fname);
	X! 	exit(0);
	X! }
	X! 
	X! /* 
	X!  * Donechild closes output file and exits child - this is called when
	X!  * EITHER child receives SIGCHLD from grandchild (shell) OR if psuedo-
	X!  * teletype closes.
	X!  */
	X! 
	X! 
	X! donechild()
	X! {
	X! 
	X! 	tvec = time((time_t *)0);
	X! 	fprintf(fscript,"\nscript done on %s", ctime(&tvec));
	X! 	(void) fclose(fscript);
	X! 	(void) close(master);
	X  	exit(0);
	X  }
	X  
	X
	X--- 172,178 -----
	X  {
	X  
	X  	ioctl(0, TIOCSETP, (char *)&b);
	X! 	printf("Script done, file is %s\n", fname);
	X  	exit(0);
	X  }
	X  
SHAR_EOF
if test 4304 -ne "`wc -c < 'scriptdiff'`"
then
	echo shar: "error transmitting 'scriptdiff'" '(should have been 4304 characters)'
fi
fi
exit 0
#	End of shell archive



More information about the Comp.unix.wizards mailing list