On Tue, 29 Feb 2000, Philip Webb wrote:
> since Lynx ^t doesn't help, i remembered strace ,
> which gives at the end of a long list (further details on request):
Good idea!
> read(0, "7", 1) = 1
> ioctl(0, 0x4004667f, [0]) = 0
> ioctl(0, 0x4004667f, [0]) = 0
> write(1, "\rFollow link (or goto link or p"..., 44) = 44
> ioctl(0, 0x4004667f, [0]) = 0
> ioctl(0, 0x4004667f, [0]) = 0
> write(1, "\33[0m\0177", 6) = 6
> read(0, "\r", 1) = 1
You were following link #7 here. I assume this is from the 'P'rint Options
page. What is your link #7?
> getpid() = 26297 (ppid 26293)
> open("/homes/purslow/tmp/L26297-2TMP.txt", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
> fxstat(2, 4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
> fxstat(2, 4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
> ioctl(4, TCGETA, 0x7fffa168) = -1 ENOTTY (Not a typewriter)
> write(4, "\n \n CHASS Information\n "..., 4293) = 4293
> close(4) = 0
> ioctl(1, TCSETAW, {B38400 opost isig icanon echo ...}) = 0
> write(1, "\r\33[?1l", 6) = 6
> sigaction(SIGINT, {SIG_DFL}, {0x410eb0, [], SA_RESETHAND|SA_NODEFER}) = 0
> write(1, "Printing file. Please wait...", 30) = 30
Now lynx is going to invoke a command via its LYSystem() function.
What command exactly depends on what link #7 is.
The following 3 lines are happening under control of lynx code, see
LYSystem():
> sigaction(SIGPIPE, {SIG_DFL}, {SIG_IGN}) = 0
> sigaction(SIGTSTP, NULL, {0xfa6d8f8, [], SA_RESETHAND|SA_NODEFER}) = 0
> sigaction(SIGTSTP, {SIG_DFL}, {0xfa6d8f8, [], SA_RESETHAND|SA_NODEFER}) = 0
Then LYSystem() calls system(), all the following is happening within the
system's system() implementation:
> sigaction(SIGCHLD, {SIG_DFL}, {SIG_DFL}) = 0
> fork() = 26308
A child process is created to execute the external command (whatever it
is). We don't see what the child process does (it isn't being traced),
but the parent lynx process now just waits:
> waitid(P_PID, 26308, <unfinished ...>
> --- SIGINT (Interrupt) ---
... and gets a SIGINT signal before the child exists.
Assuming you pressed ^g - the child process, or one of its children - mutt
or whatever - changed the tty settings so that ^G means intr (this would
show up unter 'stty -a' as 'intr = ^G', if you could look at it at it at
this stage).
> <... waitid resumed> 0x7fffa138, WEXITED|WTRAPPED) = -1 EINTR (Interrupted system
>call)
> --- SIGINT (Interrupt) ---
^G causes a SIGINT signal, the same as ^C normally, which gets delivered
to the parent (lynx) process as well as to the child. It causes the lynx
process to terminate (in addition to what it does to the child process -
probably terminate it, too).
The problem is the system's system() implementation, it doesn't behave
as it should. From a Linux system(2) man page:
system() executes a command specified in string by calling
/bin/sh -c string, and returns after the command has been
completed. During execution of the command, SIGCHLD will
be blocked, and SIGINT and SIGQUIT will be ignored.
And on FreeBSD:
The system() function hands the argument string to the command inter-
preter sh(1). The calling process waits for the shell to finish execut-
ing the command, ignoring SIGINT and SIGQUIT, and blocking SIGCHLD.
The important part here is ignoring SIGINT. Your system() doesn't do
that. What does its man page say?
For comparison, here is a similar strace from Linux, of the part where
the parent process prepares for executing an external command:
LYSystem():
| sigaction(SIGINT, {SIG_DFL}, {0x804aba0, [], SA_RESTART|0x4000000}) = 0
| sigaction(SIGPIPE, {SIG_DFL}, {SIG_IGN}) = 0
| sigaction(SIGTSTP, NULL, {0x40041d70, [], SA_RESTART|0x4000000}) = 0
| sigaction(SIGTSTP, {SIG_DFL}, {0x40041d70, [], SA_RESTART|0x4000000}) = 0
in system():
| sigaction(SIGINT, {SIG_IGN}, {SIG_DFL}) = 0
| sigaction(SIGQUIT, {SIG_IGN}, {SIG_DFL}) = 0
| sigprocmask(SIG_BLOCK, [CHLD], []) = 0
| fork() = 14065
| wait4(14065,
It can be seen that system() sets SIGINT to SIG_IGN - as expected and
documented. So when a key (be that ^C or ^G) causes a SIGINT, the child
process will (possibly) terminate, but the parent (lynx) process will
happily resume execution after that.
So why is Philip's system's system() so broken? And what can be done
about it? I don't know.
Klaus