[news.software.b] rn and rrn may wedge tty's on some versions of BSD UNIX

muller@sdcc10.ucsd.edu (Keith Muller) (10/29/89)

Subject: rn and rrn may wedge tty's on some BSD unix versions
Index: (r)rn/util.c (r)rn/final.c

Description:
	Under some versions of UNIX with BSD job control, it may be
	possible to wedge (r)rn in a state where it is stopped
	on tty input (SIGTTIN) or tty output (SIGTTOU) and the tty is
	still in the (r)rn's process group.

Repeat-By:
	1) login under csh
	2) run (r)rn
	3) type control-z to suspend (r)rn
	4) type bg to push (r)rn into the background
	5) when (r)rn stops, then type fg to bring (r)rn into the foreground

	Your terminal is now wedged. If you look at the tty from another
	terminal you will see the rn in T state (stopped on SIGTTOU).
	You can restore the tty to the csh by killing the rn with
	a kill -9 from another terminal. (Of course why would anyone put
	rn into the background???)

	This has been observed on CCI, Vaxes running 4.3BSD-Tahoe, Pyramids,
	and Sun 4's running SUNOS 4.0.1 and 4.0.3. Without going into
	a long discussion, it probably will not occur with all machines
	that provide BSD job control. 

Fix:
	Fix the signal handlers to catch SIGTTOU and SIGTTIN along with
	SIGTSTP in final.c and util.c. Remove the handler for SIGCONT.

	These fixes probably will not break anything on machines that do not
	suffer from this problem.

	Keith Muller
	University of California, San Diego
	muller@ucsd.edu

NOTE: YOUR LINE NUMBERS WILL BE DIFFERENT!

RCS file: RCS/util.c,v
retrieving revision 1.2
diff -c -r1.2 util.c
*** /tmp/,RCSt1017130	Sat Oct 28 12:49:31 1989
--- util.c	Sat Oct 28 01:12:22 1989
***************
*** 49,55 ****
  
  #ifdef SIGTSTP
      sigset(SIGTSTP,SIG_DFL);
!     sigset(SIGCONT,SIG_DFL);
  #endif
      if (shl != Nullch)
  	shell = shl;
--- 55,62 ----
  
  #ifdef SIGTSTP
      sigset(SIGTSTP,SIG_DFL);
!     sigset(SIGTTOU,SIG_DFL);
!     sigset(SIGTTIN,SIG_DFL);
  #endif
      if (shl != Nullch)
  	shell = shl;
***************
*** 88,94 ****
      signal(SIGQUIT, qstat);
  #ifdef SIGTSTP
      sigset(SIGTSTP,stop_catcher);
!     sigset(SIGCONT,cont_catcher);
  #endif
      return status;
  }
--- 95,102 ----
      signal(SIGQUIT, qstat);
  #ifdef SIGTSTP
      sigset(SIGTSTP,stop_catcher);
!     sigset(SIGTTOU,stop_catcher);
!     sigset(SIGTTIN,stop_catcher);
  #endif
      return status;
  }


RCS file: RCS/final.c,v
retrieving revision 1.1
diff -c -r1.1 final.c
*** /tmp/,RCSt1017136	Sat Oct 28 12:49:53 1989
--- final.c	Sat Oct 28 01:14:41 1989
***************
*** 28,34 ****
  {
  #ifdef SIGTSTP
      sigset(SIGTSTP, stop_catcher);	/* job control signals */
!     sigset(SIGCONT, cont_catcher);	/* job control signals */
  #endif
  
      sigset(SIGINT, int_catcher);	/* always catch interrupts */
--- 34,41 ----
  {
  #ifdef SIGTSTP
      sigset(SIGTSTP, stop_catcher);	/* job control signals */
!     sigset(SIGTTOU, stop_catcher);	/* job control signals */
!     sigset(SIGTTIN, stop_catcher);	/* job control signals */
  #endif
  
      sigset(SIGINT, int_catcher);	/* always catch interrupts */
***************
*** 140,150 ****
  	};
  #endif
  
- #ifdef SIGTTOU
- #ifndef lint
-     sigignore(SIGTTOU);
- #endif lint
- #endif
  #ifdef DEBUGGING
      if (debug) {
  	printf("\nSIG%s--.newsrc not restored in debug\n",signame[signo]);
--- 147,152 ----
***************
*** 186,192 ****
  /* come here on stop signal */
  
  int
! stop_catcher()
  {
      if (!waiting) {
  	checkpoint_rc();		/* good chance of crash while stopped */
--- 188,195 ----
  /* come here on stop signal */
  
  int
! stop_catcher(signo)
! int signo;
  {
      if (!waiting) {
  	checkpoint_rc();		/* good chance of crash while stopped */
***************
*** 195,231 ****
  	if (debug)
  	    write(2,"stop_catcher\n",13);
  #endif
! 	sigset(SIGTSTP,SIG_DFL);	/* enable stop */
  #ifdef BSD42
! 	sigsetmask(sigblock(0) & ~(1 << (SIGTSTP-1)));
  #endif
! 	kill(0,SIGTSTP);		/* and do the stop */
!     }
!     sigset(SIGTSTP,stop_catcher);	/* unenable the stop */
! }
! 
! /* come here on cont signal */
! 
! int
! cont_catcher()
! {
!     sigset(SIGCONT,cont_catcher);
!     savetty();
  #ifdef MAILCALL;
!     mailcount = 0;			/* force recheck */
  #endif
!     if (!panic) {
! 	if (!waiting) {
! #ifdef DEBUGGING
! 	    if (debug)
! 		write(2,"cont_catcher\n",13);
! #endif
! 	    noecho();			/* set no echo */
! 	    crmode();			/* set cbreak mode */
! 	    forceme("\f");		/* cause a refresh */
  					/* (defined only if TIOCSTI defined) */
! 	}
      }
  }
  #endif
- 
--- 198,221 ----
  	if (debug)
  	    write(2,"stop_catcher\n",13);
  #endif
! 	sigset(signo,SIG_DFL);	/* enable stop */
  #ifdef BSD42
! 	sigsetmask(sigblock(0) & ~(1 << (signo-1)));
  #endif
! 	kill(0,signo);		/* and do the stop */
!     	savetty();
  #ifdef MAILCALL;
!     	mailcount = 0;			/* force recheck */
  #endif
!     	if (!panic) {
! 	    if (!waiting) {
! 	    	noecho();			/* set no echo */
! 	    	crmode();			/* set cbreak mode */
! 	    	forceme("\f");		/* cause a refresh */
  					/* (defined only if TIOCSTI defined) */
! 	    }
!     	}
      }
+     sigset(signo,stop_catcher);	/* unenable the stop */
  }
  #endif