[comp.bugs.4bsd] Meta key disappears and decctlq is on after suspending

hedrick@geneva.rutgers.edu (Charles Hedrick) (11/19/89)

>About a third of the time I suspend emacs and then go back in, the
>Meta keys don't work (I can still use ESC) and ^S and ^Q are trapped.
>If I suspend emacs again, a stty command tells me that decctlq is on.
>And when I go back into emacs, everything is OK again.

This is a bug in the BSD socket code.  The problem is that rlogin
relies on "urgent data" to change the terminal mode on the remote
host.  If urgent data happens to arrive while the kernel is processing
previous data, it can be lost.  What happens is that there is a loop
over data that has already arrived, giving it to the process that is
reading it.  If urgent data happens to arrive while you are in that
loop, the loop will continue past it.  At that point the data is
regarded as out of date, and will not be ignored by the ioctl that
asks for urgent data.

This normally shows up only when you rlogin to a machine that is very
much faster than your local one.  It's pretty clear why that should
be.  The problem depends upon a second packet arriving while the first
one is still being processed, and that's obviously more likely when
the machine doing the processing is relatively slow.  We first saw it
with Sun 3/50's logged into Pyramids.  The following fix is from our
SunOS 4.0.1 source.  I'm fairly sure you could use the same fix in
4.0.3 and 4.0.3c.  I believe the fix has to be in the local machine,
i.e. your Sun 3/80.  This diff is for uipc_socket.c.  It has been
reported to Berkeley, Sun, and Pyramid, but long enough ago that I'm
pretty sure that if they were going to accept it, they would have done
so already.  So you should probably report it to Sun yourself.

*** /tmp/geta635	Sat Nov 18 17:36:30 1989
--- /tmp/getb635	Sat Nov 18 17:36:31 1989
***************
*** 436,441 ****
--- 436,444 ----
  	struct mbuf *nextrecord;
  	int moff;
  
+ /* RU 29 - need procp for test of SIGURG. see below */
+ 	register struct proc *p = u.u_procp;
+ 
  	if (rightsp)
  		*rightsp = 0;
  	if (aname)
***************
*** 568,575 ****
  		}
  	}
  	moff = 0;
! 	tomark = so->so_oobmark;
  	while (m && uio->uio_resid > 0 && error == 0) {
  		if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
  			panic("receive 3");
  		len = uio->uio_resid;
--- 571,594 ----
  		}
  	}
  	moff = 0;
! /*
!  * RU 29 - move calculation of tomark into loop, so we exit
!  * if push happens to arrive while we are in the loop with
!  * priority lowered.  Also, arrange to exit if we get SIGURG,
!  * so that we don't read over the urgent data, making it
!  * invalid.
!  */
! 	if (flags & MSG_PEEK)
! 	  tomark = so->so_oobmark;
! 	if ((((p)->p_sig &~ (p)->p_sigmask) & sigmask(SIGURG)) &&
! 	    ((p)->p_flag&STRC ||
! 	     ((sigmask(SIGURG) & (p)->p_sigignore) == 0)))
! 	  error = EINTR;
! 	else 
  	while (m && uio->uio_resid > 0 && error == 0) {
+ /* RU 29 - move tomark inside loop */
+ 	        if ((flags & MSG_PEEK) == 0)
+ 	    	  tomark = so->so_oobmark;
  		if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
  			panic("receive 3");
  		len = uio->uio_resid;
***************
*** 616,621 ****
--- 635,645 ----
  			if (tomark == 0)
  				break;
  		}
+ /* RU 29 - exit if now have a SIGURG */
+ 		if ((((p)->p_sig &~ (p)->p_sigmask) & sigmask(SIGURG)) &&
+ 		    ((p)->p_flag&STRC ||
+ 		     ((sigmask(SIGURG) & (p)->p_sigignore) == 0)))
+ 		  break;
  	}
  	if ((flags & MSG_PEEK) == 0) {
  		if (m == 0)