lynx-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: lynx-dev Problem with ^Z suspending


From: Klaus Weide
Subject: Re: lynx-dev Problem with ^Z suspending
Date: Sat, 23 Jan 1999 07:10:46 -0600 (CST)

On Sat, 23 Jan 1999, Kari E. Hurtta wrote:
> Klaus Weide:
> > The short version: behavior in response to ^Z does not work reliably
> > if lynx is started from a shell script.
> > 
> > Description:
> > When the lynx binary is started directly from the shell prompt, suspending
> > with ^Z (which sends SIGTSTP signal) and resuming with "fg" works fine.
> > 
> > When the lynx binary is started from a shell script, say runlynx.sh which
> > can be as simple as
> >      #!/bin/sh
> >      /PATH/TO/lynx
> [ snip ]
> 
> That kind invocation is problems with cob control if then program
> (which is invoced via script) catch SIGTSTP signal and does
> some work in signal handler (such as returning terminal to
> canonical mode) before stopping program.
> 
> Possible sequnce of events:

That agrees mostly with what I've been able to figure out.
Filling in more details:

>       - Ctrl-Z is pressed.
>       - SIGTSTP is send to job group. In this job group have two
>               processes:
>               a) /bin/sh
>               b) lynx
>       - /bin/sh stops
>       - shell (which is started that /bin/sh script)
>         got SIGCHLD because child of it is stopped

(or just a return from wait* - but that doesn't matter)

>       - shell does wait* to see what is happened
>       - shell returns terminal to canonical mode because
>         it is not and child of it is stopped and
>         prints prompts

More important is that the parent shell changes the terminal
process group back to itself.

>       - SIGTSTP handler of lynx is called
>         and it prints now own stuff to terminal
>         (to put terminal to known state)

Here's where the most interesting things happen:

The signal handler (a) writes some characters to the tty (to position
the cursor on last screen line), then (b) does something which
translates into an ioctl(1, TCSETSW,...) system call.

Now, that ioctl results in a SIGTTOU being generated, because the
tty driver detects that the controlling tty has now a different
process group.  That happens even if 'stty -tostop' is in effect
(the default for me).  If 'stty tostop' is in effect instead, the
SIGTTOU is already generated by (a).

This behavior may be very kernel/driver/library specific, or might
even depend on how ncurses was compiled, so I'd still like to know
whether other folks are seeing the same.

The SIGTTOU results in the process being stopped prematurely, while
it's already on the way to stop itself.  When it gets woken up later
as the result of "fg", it doesn't detect that that's what's happened,
instead it still think it's time to stop itself, which it does.

This can be seen by attaching to the process with gdb or strace.
I can confirm that it's the SIGTTOU that is causing the re-suspending
by putting a 'signal(SIGTTOU, SIG_IGN)' in the Lynx code: when I do
that, it doesn't happen any more.

I don't suggest that as a general solution, first because I don't know
how widespread the problem is, second because sometimes being stopped
in response to SIGTTOU may be a Good Thing, third because it should be
signal handler's responsibility, fourth because it doesn't really
solve the problem that the ioctl() fails (the termios isn't completely
being restored to the state it should).  The signal handler is the one
from ncurses (Lynx doesn't install its own unless compiled with
slang).

The SIGTSTP signal handler could prevent this kind of thing by
 - blocking SIGTTOU (and maybe others) while doing its
   output thing (and checking returns from write and ioctl); or
 - a handler for SIGTTOU that detects when it's being called
   in this situation, and sets a flag for the SIGTSTP handler to
   process later, then kill(,SIGTSTOP) itself; or
 - a handler for SIGCONT that detects when it's being called
   in this situation, and sets a flag for the SIGTSTP handler to
   process.
The second and third options seem more portable.  

So I suggest the ncurses signal handler should do one of these
things, and it is not the case now, at least on my system.
I hope Tom comment on this.

I don't really understand why I haven't observed the same problem
with other ncurses programs (using the same library version).
What's special about how Lynx uses curses?  Does it do something
other programs don't do?  It could also be that I don't usually
invoke other ncurses programs throug intermediary shells.


> I remember that I solved that problem in my kehpager program
> which I done some years ago that way that that program creates
> own job (via setpgrp if I remember correctly) and then set terminal
> to that group via tcsetprgp. That way on curren foreground job
> of terminal have only that my program (abnd shell script is not on
> foreground job) and because of that SIGTSTP (result of Ctrl-Z)
> is sent only to that my program.
> 
> There was such issues that that my program needed also to fork
> to be sure that on original process group there was
> always at least one program (so that that process group did
> not vanished).
> 
> Yes. That is messy.

That doesn't dound like something Lynx should do.

> I remember that I see that problem first time on system where
> was more than one CPU (otherwise original job controlling
> shell does not win race because of scheduling policy.) :-)

Not the case here.

> / Kari Hurtta

   Klaus 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]