Current-Users archive

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

Re: script(1) bug?



    Date:        Fri, 28 Aug 2026 10:15:04 +0200
    From:        Thomas Klausner <wiz%netbsd.org@localhost>
    Message-ID:  <apFDEZXxMK1Y-xB3%exadelic.gatalith.at@localhost>

  | I can't reproduce this on my (bare-metal) machine, can someone please
  | try to reproduce it?

I can't reproduce it either, but there looks to be a simple race condition
in the code, which a simple detector would perhaps stumble across sometimes.

script works with 3 processes

	script itself (the process invoked) which sets things up
		then reads from its stdin, and send what it reads
		(via pty, not pipe) to the invoked process

	a child process which runs the command (reads from the pty
		from its parent, writes back to that pty, ie: the pty
		(slave side) becomes its stdin/stdout)

	a grandchild process which collects the output from the
	command (everything written to the pty, read from the master side)
	and writes that 	to the typescript file, and script's stdout.

The grandchild process exits when the pty it is reading from is closed.
Before then, if -f was not given to script, it writes to the typescript
file only every 30 seconds (or when the stdio output buffer fills, if
something is generating lots of output).   Without -f, the typescript
file will only actually get anything written to it, after 30 seconds,
or after the pty it is reading from has closed, and the typescript
file is fclosed (or each time the stdio buffer fills - very unlikely
to ever happen in these small tests).

the child process exits when the command is done

the script process exits as soon as the child process exits (it catches
a SIGCHLD, wait()'s for the child, then exits).

If the child process exits very quickly, script itself will exit,
but the grandchild process might not have even started yet (it will
have been fork'd, but no guarantee that the kernel has scheduled it
to run).

Hence, if one looks for the typescript content very quickly after script
exits, nothing might be there - yet.   It should turn up, eventually.

This might be able to be fixed by having the child process explicitly close
down the output pty, rather than that being just a side effect of the exit(),
and then wait on its child (the grandchild process) to exit, before it exits
itself, but as I can't reproduce the actual issue, there's no point for me
to attempt to fix it, as I wouldn't be able to tell if anything was actually
behaving differently (unless I botched it and completely broke things).

Another possibility might be to swap the child/grandchild roles.   Then
when the invoked process exits, the slave side of the pty is closed, and
the output process (current grandchild) would detect that, and exit, which
the script process would detect and exit as well - doing it that way should
guarantee that the typescript file has been closed before script exits,
but it would need more changes to correctly pass back the exit status from
the command so script's -e option would keep working.

I haven't looked closely enough at what logic is involved in all of this
to be 100% convinced this is the cause, but it looks quite likely.

I doubt that it makes any difference (to this) whether script is reading
from a tty or not (yes, it does make some difference to how things are
setup, but nothing material there that I can see), nor do potential stdio
flushing issues (which might be resolved by the process that should not
be doing that calling _exit() instead of exit()) look to be related either.

kre



Home | Main Index | Thread Index | Old Index