Date:        Mon, 2 Mar 2026 02:32:32 -0800
    From:        Ben Ashton <[email protected]>
    Message-ID:  <[email protected]>

  | That IS what's going on. Setsid makes sleep the leader of a new process 
  | group.

Yes, but bash doesn't know that, we know what the setsid command is
intended to do, bash doesn't.

  | Runing this script:
  |
  |    #!/usr/bin/env bash
  |    set -m
  |    (
  |      setsid sleep 40 &

Imagine what happens here, in the far more common case where the
setsid is not present, and the command is just "sleep 40 &"

  |      pid=$!
  |      echo "Sleep pid: $pid"
  |      sleep 20
  |      kill -TERM -$pid
  |      echo "Here"
  |    )

And the rest of that is all unchanged.   When bash sees the

        kill -TERM -17585

it can tell you are trying to kill a process group and the process
group associated with process 17585 which it sees in the job table
as one if its child processes.   In its job table (which bash provides
no way I know of to interrogate, but you would be able to see if it had
the jobid builtin added - perhaps one of the people who knows how to
create loadable builtins for bash might care to create one for it, the
code should be simple, it just dumps info from the internal jobs table
to stdout) you'd see that to bash, the pid ($!) of that job is 17585
and the pgrp is 17584.

So (I am guessing) to bash it appears as if you're trying to send
a TERM signal to the process group to which process 17585 is the
job leader, and it sends that signal to that process group.

If the setsid were not there, that would be exactly right.

This is what I meant by the shell attempting to intuit what the
script intends, and since use of setsid() in scripts I would
expect is extremely rare, it is probably right more often than
it is wrong -- though perhaps bash's builtin kill could do with
having an option added to tell it to simply do as instructed.   Or
you can just run /bin/kill which has no access to bash's jobs table
when that is your intent.

kre

ps: there is also no requirement that job control be turned off in
subshell environments, some shells (like bash apparently) do so,
others do not (dash doesn't, nor does ksh93).  In those other shells,
the setsid(2) does nothing (fails) -- NetBSD has setsid(1) command, so I
needed to make one - my version just errors and exits if the setsid() sys
call fails, which it does with dash, ksh93, and the NetBSD sh (another
ash descendant, like dash) when the "set -m" is there.

Reply via email to