• Re: Why does getppid() still return old parent pid after setsid()?

    From Lew Pitcher@21:1/5 to Kenny McCormack on Sat Nov 9 15:49:33 2024
    On Sat, 09 Nov 2024 09:25:22 +0000, Kenny McCormack wrote:

    In article <vgl8h1$385vs$1@dont-email.me>, <Muttley@DastartdlyHQ.org> wrote:
    I've tried this code on both MacOS and Linux yet the child process getppid() >>still returns its original parent process instead of "1" for init which is >>what I'd expect. Isn't setsid() supposed to completely detach the child or >>have I misunderstood?
    [snip]
    The usual method for ensuring that a process *does* have getppid() == 1 is the classic "double fork". The parent forks(), the child then forks() and exits. The grandchild then does the work (either directly or via exec()).

    Some systems (notably BSD) provide a daemon(3) function that does this. GNU glibc provides this function by default (feature test macro _DEFAULT_SOURCE) since glibc 2.21. W. Richard Stevens discusses the details in chapter 13
    of "Advanced Programming in the Unix Environment" (aka the "APUE" book).


    [snip]

    HTH
    --
    Lew Pitcher
    "In Skills We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Lew Pitcher on Sat Nov 9 19:01:02 2024
    On Sat, 09 Nov 2024 15:49:33 +0000, Lew Pitcher wrote:

    On Sat, 09 Nov 2024 09:25:22 +0000, Kenny McCormack wrote:

    In article <vgl8h1$385vs$1@dont-email.me>, <Muttley@DastartdlyHQ.org> wrote:
    I've tried this code on both MacOS and Linux yet the child process getppid() >>>still returns its original parent process instead of "1" for init which is >>>what I'd expect. Isn't setsid() supposed to completely detach the child or >>>have I misunderstood?
    [snip]
    The usual method for ensuring that a process *does* have getppid() == 1 is >> the classic "double fork". The parent forks(), the child then forks() and >> exits. The grandchild then does the work (either directly or via exec()).

    Some systems (notably BSD) provide a daemon(3) function that does this.

    I have to correct myself here. According to the BUGS section of the
    glibc daemon(3) manpage:
    The GNU C library implementation of this function was taken from BSD,
    and does not employ the double-fork technique (i.e., fork(2), set-
    sid(2), fork(2)) that is necessary to ensure that the resulting daemon
    process is not a session leader.

    GNU
    glibc provides this function by default (feature test macro _DEFAULT_SOURCE) since glibc 2.21. W. Richard Stevens discusses the details in chapter 13
    of "Advanced Programming in the Unix Environment" (aka the "APUE" book).


    [snip]

    HTH




    --
    Lew Pitcher
    "In Skills We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Muttley@DastartdlyHQ.org@21:1/5 to All on Mon Nov 11 10:02:45 2024
    On Sat, 9 Nov 2024 09:25:22 -0000 (UTC)
    gazelle@shell.xmission.com (Kenny McCormack) boring babbled:
    In article <vgl8h1$385vs$1@dont-email.me>, <Muttley@DastartdlyHQ.org> wrote: >>I've tried this code on both MacOS and Linux yet the child process getppid() >>still returns its original parent process instead of "1" for init which is >>what I'd expect. Isn't setsid() supposed to completely detach the child or >>have I misunderstood?

    I suppose the obvious question at this point is: Why do you care? What's
    the underlying issue?

    Just curiousity mainly. I did setsid() and ignored SIGCLD so I wouldn't get zombie processes but noticed that getppid() didn't return 1. I'd forgotten about double fork to be fair - I need to re-read Stevens at some point! - but can't help thinking they should be a single shot OS call to completely
    seperate the child from parent. Yes, daemon() will do it as a single function call but I imagine that just does a double fork underneath anyway.

    under Linux, there is also the re-parenting "prctl".

    I didn't know that, thanks.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Muttley on Mon Nov 11 15:20:25 2024
    On Mon, 11 Nov 2024 10:02:45 +0000, Muttley wrote:

    On Sat, 9 Nov 2024 09:25:22 -0000 (UTC)
    gazelle@shell.xmission.com (Kenny McCormack) boring babbled:
    In article <vgl8h1$385vs$1@dont-email.me>, <Muttley@DastartdlyHQ.org> wrote: >>>I've tried this code on both MacOS and Linux yet the child process getppid() >>>still returns its original parent process instead of "1" for init which is >>>what I'd expect. Isn't setsid() supposed to completely detach the child or >>>have I misunderstood?

    I suppose the obvious question at this point is: Why do you care? What's >>the underlying issue?

    Just curiousity mainly. I did setsid() and ignored SIGCLD so I wouldn't get zombie processes but noticed that getppid() didn't return 1. I'd forgotten about double fork to be fair - I need to re-read Stevens at some point! - but can't help thinking they should be a single shot OS call to completely seperate the child from parent. Yes, daemon() will do it as a single function call but I imagine that just does a double fork underneath anyway.

    According to daemon(3) from glibc, the glibc version (common on Linux systems) does not perform a double fork(2). Specifically,
    "The GNU C library implementation of this function was taken from BSD,
    and does not employ the double-fork technique (i.e., fork(2), set-
    sid(2), fork(2)) that is necessary to ensure that the resulting daemon
    process is not a session leader. Instead, the resulting daemon
    session leader. On systems that follow System V semantics (e.g.,
    Linux), this means that if the daemon opens a terminal that is not
    already a controlling terminal for another session, then that terminal
    will inadvertently become the controlling terminal for the daemon."

    [snip]

    --
    Lew Pitcher
    "In Skills We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rainer Weikusat@21:1/5 to Muttley@DastartdlyHQ.org on Mon Nov 11 15:53:44 2024
    Muttley@DastartdlyHQ.org writes:
    I've tried this code on both MacOS and Linux yet the child process getppid() still returns its original parent process instead of "1" for init which is what I'd expect. Isn't setsid() supposed to completely detach the child or have I misunderstood?

    A session is a set of processes associated with a particular controlling terminal, namely, that of the session leader (or no controlling terminal
    if the session leader doesn't have one). setsid creates an unassociated
    new session lead by the process which called it. It has no effect on
    parent/ child relationships of processes.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Kenny McCormack on Mon Nov 11 17:08:20 2024
    On Sat, 09 Nov 2024 09:25:22 +0000, Kenny McCormack wrote:
    [snip]
    As
    far as I know, in classic Unix, the only way for a process to get "re-parented" is to have the parent die. Of course, as others have noted, under Linux, there is also the re-parenting "prctl".

    Kenny, could you elaborate on the use of prctl() to "reparent" a process?
    I've not seen examples of how to do this, and the prctl(2) manpage doesn't explicitly indicate the options necessary.

    I don't see any option that controls or modifies a process PPID. The only prctl(2) options that I can see relating to "reparenting" are the PR_SET_CHILD_SUBREAPER and PR_GET_CHILD_SUBREAPER options that
    seem to govern who gets SIGCHLD on the child's death. Is this what you
    mean by "reparenting"?

    [snip]


    --
    Lew Pitcher
    "In Skills We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Lew Pitcher on Mon Nov 11 17:30:47 2024
    Lew Pitcher <lew.pitcher@digitalfreehold.ca> writes:
    On Mon, 11 Nov 2024 10:02:45 +0000, Muttley wrote:

    On Sat, 9 Nov 2024 09:25:22 -0000 (UTC)
    gazelle@shell.xmission.com (Kenny McCormack) boring babbled:
    In article <vgl8h1$385vs$1@dont-email.me>, <Muttley@DastartdlyHQ.org> wrote:
    I've tried this code on both MacOS and Linux yet the child process getppid()
    still returns its original parent process instead of "1" for init which is >>>>what I'd expect. Isn't setsid() supposed to completely detach the child or >>>>have I misunderstood?

    I suppose the obvious question at this point is: Why do you care? What's >>>the underlying issue?

    Just curiousity mainly. I did setsid() and ignored SIGCLD so I wouldn't get >> zombie processes but noticed that getppid() didn't return 1. I'd forgotten >> about double fork to be fair - I need to re-read Stevens at some point! - but
    can't help thinking they should be a single shot OS call to completely
    seperate the child from parent. Yes, daemon() will do it as a single function
    call but I imagine that just does a double fork underneath anyway.

    According to daemon(3) from glibc, the glibc version (common on Linux systems) >does not perform a double fork(2). Specifically,
    "The GNU C library implementation of this function was taken from BSD,
    and does not employ the double-fork technique (i.e., fork(2), set-
    sid(2), fork(2)) that is necessary to ensure that the resulting daemon
    process is not a session leader. Instead, the resulting daemon
    session leader. On systems that follow System V semantics (e.g.,
    Linux), this means that if the daemon opens a terminal that is not
    already a controlling terminal for another session, then that terminal
    will inadvertently become the controlling terminal for the daemon."

    That's why POSIX has the 'O_NOCTTY' flag for open.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to lew.pitcher@digitalfreehold.ca on Mon Nov 11 20:15:05 2024
    In article <vgtdm4$11fog$2@dont-email.me>,
    Lew Pitcher <lew.pitcher@digitalfreehold.ca> wrote:
    ...
    Kenny, could you elaborate on the use of prctl() to "reparent" a process? >I've not seen examples of how to do this, and the prctl(2) manpage doesn't >explicitly indicate the options necessary.

    I don't see any option that controls or modifies a process PPID. The only >prctl(2) options that I can see relating to "reparenting" are the >PR_SET_CHILD_SUBREAPER and PR_GET_CHILD_SUBREAPER options that
    seem to govern who gets SIGCHLD on the child's death. Is this what you
    mean by "reparenting"?

    Yes, that's it. The man page text even includes the word 'reparented'.

    Note; I've never actually used this call, but I can imagine situations
    where it could be used. The man page seems pretty clear as to what it does.

    --
    The difference between communism and capitalism?
    In capitalism, man exploits man. In communism, it's the other way around.

    - Daniel Bell, The End of Ideology (1960) -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Muttley on Mon Nov 11 20:57:23 2024
    On Mon, 11 Nov 2024 10:02:45 -0000 (UTC), Muttley wrote:

    can't help thinking they should be a single shot OS call to completely seperate the child from parent.

    I guess it’s not that important.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to ldo@nz.invalid on Tue Nov 12 12:15:29 2024
    In article <vgtr3i$15srv$2@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Mon, 11 Nov 2024 10:02:45 -0000 (UTC), Muttley wrote:

    can't help thinking they should be a single shot OS call to completely
    seperate the child from parent.

    I guess its not that important.

    It *is* "that important". And daemon(3) fills the role.

    However, it may be true that it doesn't fully fill it - and maybe that it should also do the "double fork".

    --
    The whole aim of practical politics is to keep the populace alarmed (and hence clamorous
    to be led to safety) by menacing it with an endless series of hobgoblins, all of them imaginary.

    H. L. Mencken

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Geoff Clare@21:1/5 to Muttley on Tue Nov 12 13:39:25 2024
    Muttley wrote:

    I've tried this code on both MacOS and Linux yet the child process getppid() still returns its original parent process instead of "1" for init which is what I'd expect. Isn't setsid() supposed to completely detach the child or have I misunderstood?

    As others have pointed out, you have misunderstood, but I don't
    think anyone has quoted a relevant bit of POSIX in the definition
    of "Parent Process ID" (XBD 3.253 in POSIX.1-2024):

    The parent process ID of a process is the process ID of its
    creator, for the lifetime of the creator. After the creator's
    lifetime has ended, the parent process ID is the process ID of an
    implementation-defined system process.

    --
    Geoff Clare <netnews@gclare.org.uk>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Muttley@DastartdlyHQ.org@21:1/5 to All on Tue Nov 12 15:13:27 2024
    On Tue, 12 Nov 2024 13:39:25 +0000
    Geoff Clare <geoff@clare.See-My-Signature.invalid> boring babbled:
    Muttley wrote:

    I've tried this code on both MacOS and Linux yet the child process getppid() >> still returns its original parent process instead of "1" for init which is >> what I'd expect. Isn't setsid() supposed to completely detach the child or >> have I misunderstood?

    As others have pointed out, you have misunderstood, but I don't
    think anyone has quoted a relevant bit of POSIX in the definition
    of "Parent Process ID" (XBD 3.253 in POSIX.1-2024):

    The parent process ID of a process is the process ID of its
    creator, for the lifetime of the creator. After the creator's
    lifetime has ended, the parent process ID is the process ID of an
    implementation-defined system process.

    Fair enough. So reparenting can't happen so long as the parent exists no matter what the child does.

    I could envisage scenarios where the child process being able to reparent itself - given correct permissions - could be useful. Wonder if any OS's implement that?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to Muttley@DastartdlyHQ.org on Tue Nov 12 21:24:52 2024
    On 2024-11-08, Muttley@DastartdlyHQ.org <Muttley@DastartdlyHQ.org> wrote:
    I've tried this code on both MacOS and Linux yet the child process getppid() still returns its original parent process instead of "1" for init which is what I'd expect. Isn't setsid() supposed to completely detach the child or have I misunderstood?

    No; it's because you put a 1 second delay into the parent to keep it
    alive, whereas the child calls getppid() without any such timed
    scheduling delay.

    Because 1 second is an eternity, you've practically guaranteed that the
    child will get the original parent pid. The only thing that would make
    it air tight would be if the parent waited for the child's termination
    instead of sleeping.

    setsid has to do with the TTY session, and manipulates the group ID.
    If you read descriptions of it carefully, you will see that it has
    nothing to do with detaching from a parent process.

    To detach from a parent process, do a double fork to create a
    grandchild. Have the child quit. Then the grandchild will be orphaned
    and reparented to some process (typically PID 1). The timing of
    that is "racy"; it has to do with when the intermediate child
    terminates, until which time, the grandchild has that process as its
    parent PID.


    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @Kazinator@mstdn.ca

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Muttley@DastartdlyHQ.org@21:1/5 to All on Wed Nov 13 08:12:13 2024
    On Tue, 12 Nov 2024 21:24:52 -0000 (UTC)
    Kaz Kylheku <643-408-1753@kylheku.com> boring babbled:
    On 2024-11-08, Muttley@DastartdlyHQ.org <Muttley@DastartdlyHQ.org> wrote:
    I've tried this code on both MacOS and Linux yet the child process getppid() >> still returns its original parent process instead of "1" for init which is >> what I'd expect. Isn't setsid() supposed to completely detach the child or >> have I misunderstood?

    No; it's because you put a 1 second delay into the parent to keep it
    alive, whereas the child calls getppid() without any such timed
    scheduling delay.

    True, I fixed it soon after, should have been the child that executed it.
    But it doesn't make any difference but now I know why.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Harnden@21:1/5 to Kenny McCormack on Wed Nov 13 13:38:58 2024
    On 12/11/2024 12:15, Kenny McCormack wrote:
    In article <vgtr3i$15srv$2@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Mon, 11 Nov 2024 10:02:45 -0000 (UTC), Muttley wrote:

    can't help thinking they should be a single shot OS call to completely
    seperate the child from parent.

    I guess its not that important.

    It *is* "that important". And daemon(3) fills the role.

    However, it may be true that it doesn't fully fill it - and maybe that it should also do the "double fork".


    Should it be: parent fork, child setsid, child fork, grandchild exec
    or: parent fork, child fork, grandchild setsid, grandchild exec

    ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Richard Harnden on Wed Nov 13 15:00:53 2024
    On Wed, 13 Nov 2024 13:38:58 +0000, Richard Harnden wrote:

    On 12/11/2024 12:15, Kenny McCormack wrote:
    In article <vgtr3i$15srv$2@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Mon, 11 Nov 2024 10:02:45 -0000 (UTC), Muttley wrote:

    can't help thinking they should be a single shot OS call to completely >>>> seperate the child from parent.

    I guess its not that important.

    It *is* "that important". And daemon(3) fills the role.

    However, it may be true that it doesn't fully fill it - and maybe that it
    should also do the "double fork".


    Should it be: parent fork, child setsid, child fork, grandchild exec
    or: parent fork, child fork, grandchild setsid, grandchild exec

    With "parent fork, child fork, grandchild setsid, grandchild exec", while
    the grandchild's PPID is (or should be, sans race conditions) == 1 (init),
    it's SID (session ID) and PGID (process group ID) are now equal to its
    PID, putting the grandchild in a different session and process group
    than the original parent, and making the grandchild a session and group leader

    However, with "parent fork, child setsid, child fork, grandchild exec",
    while the grandchild's PPID is also (or should also be) == 1 (with the
    same caveats regarding race conditions), it's SID (session ID) and PGID (process group ID) are equal to its (real) parent. This also puts the grandchild in a different session and process group than the original parent, BUT, makes the grandchild a member of that session and group, instead
    of its leader.

    The difference is that the "parent fork, child fork, grandchild setsid, grandchild exec" sequence can still acquire a controlling terminal if it
    opens a terminal device WITHOUT the O_NOCTTY option. HOWEVER, the "parent
    fork, child setsid, child fork, grandchild exec" scenario CANNOT acquire
    a controlling terminal, no matter what options it opens a terminal device
    with.

    The "double fork" of the "double fork scenario" permits the child process
    to become a session and group leader (something that the parent process
    may not be able to do (if that parent process is already a process
    group leader, see setsid(2)). Because that child process is a session
    and group leader, it cannot "inherit" a controlling terminal; but it
    can open(2) a controlling terminal if it wishes.

    But, in the "double fork scenario", the child process fork(2)s the grandchild process immediately after setsid(2), then exits. This leaves the grandchild
    a) with a PPID of 1 (courtesy of the child process termination),
    b) a session ID which is not equal to its PID,
    c) a process group id which is not equal to its PID
    (so it is neither a session leader nor a process group leader),
    d) without a controlling terminal (courtesy of the setsid(2)), and
    e) without the ability to obtain a controlling terminal (because it is
    neither a session leader nor a process group leader).

    The grandchild can access files and devices, so it /has/ the ability
    to interact with the outside world, but on its own terms. The only
    way (highly simplified) the outside world can interact with the grandchild, though, is through root-generated signals, which the grandchild can handle
    with appropriate signal-handling logic.


    --
    Lew Pitcher
    "In Skills We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Harnden@21:1/5 to Lew Pitcher on Wed Nov 13 17:23:26 2024
    On 13/11/2024 15:00, Lew Pitcher wrote:
    On Wed, 13 Nov 2024 13:38:58 +0000, Richard Harnden wrote:

    On 12/11/2024 12:15, Kenny McCormack wrote:
    In article <vgtr3i$15srv$2@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Mon, 11 Nov 2024 10:02:45 -0000 (UTC), Muttley wrote:

    can't help thinking they should be a single shot OS call to completely >>>>> seperate the child from parent.

    I guess its not that important.

    It *is* "that important". And daemon(3) fills the role.

    However, it may be true that it doesn't fully fill it - and maybe that it >>> should also do the "double fork".


    Should it be: parent fork, child setsid, child fork, grandchild exec
    or: parent fork, child fork, grandchild setsid, grandchild exec

    With "parent fork, child fork, grandchild setsid, grandchild exec", while
    the grandchild's PPID is (or should be, sans race conditions) == 1 (init), it's SID (session ID) and PGID (process group ID) are now equal to its
    PID, putting the grandchild in a different session and process group
    than the original parent, and making the grandchild a session and group leader

    However, with "parent fork, child setsid, child fork, grandchild exec",
    while the grandchild's PPID is also (or should also be) == 1 (with the
    same caveats regarding race conditions), it's SID (session ID) and PGID (process group ID) are equal to its (real) parent. This also puts the grandchild in a different session and process group than the original parent, BUT, makes the grandchild a member of that session and group, instead
    of its leader.

    The difference is that the "parent fork, child fork, grandchild setsid, grandchild exec" sequence can still acquire a controlling terminal if it opens a terminal device WITHOUT the O_NOCTTY option. HOWEVER, the "parent fork, child setsid, child fork, grandchild exec" scenario CANNOT acquire
    a controlling terminal, no matter what options it opens a terminal device with.

    The "double fork" of the "double fork scenario" permits the child process
    to become a session and group leader (something that the parent process
    may not be able to do (if that parent process is already a process
    group leader, see setsid(2)). Because that child process is a session
    and group leader, it cannot "inherit" a controlling terminal; but it
    can open(2) a controlling terminal if it wishes.

    But, in the "double fork scenario", the child process fork(2)s the grandchild process immediately after setsid(2), then exits. This leaves the grandchild a) with a PPID of 1 (courtesy of the child process termination),
    b) a session ID which is not equal to its PID,
    c) a process group id which is not equal to its PID
    (so it is neither a session leader nor a process group leader),
    d) without a controlling terminal (courtesy of the setsid(2)), and
    e) without the ability to obtain a controlling terminal (because it is
    neither a session leader nor a process group leader).

    The grandchild can access files and devices, so it /has/ the ability
    to interact with the outside world, but on its own terms. The only
    way (highly simplified) the outside world can interact with the grandchild, though, is through root-generated signals, which the grandchild can handle with appropriate signal-handling logic.



    Thanks very much.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Muttley@DastartdlyHQ.org@21:1/5 to All on Fri Nov 8 14:51:13 2024
    I've tried this code on both MacOS and Linux yet the child process getppid() still returns its original parent process instead of "1" for init which is
    what I'd expect. Isn't setsid() supposed to completely detach the child or
    have I misunderstood?

    int main()
    {
    printf("Parent pid %d\n",getpid());
    switch(fork())
    {
    case -1:
    perror("fork");
    return 0;
    case 0:
    // child
    break;
    default:
    // Parent
    sleep(1);
    return 0;
    }

    setsid();
    printf("Child parent = %d\n",getppid());
    return 0;
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lew Pitcher@21:1/5 to Muttley on Fri Nov 8 15:30:21 2024
    On Fri, 08 Nov 2024 14:51:13 +0000, Muttley wrote:

    I've tried this code on both MacOS and Linux yet the child process getppid() still returns its original parent process instead of "1" for init which is what I'd expect. Isn't setsid() supposed to completely detach the child or have I misunderstood?

    I cant claim to be an expert on this, but my understanding of the situation
    is this:

    Each process maintains a /number/ of relationships with other processes,
    /one/ of which is ppid (parent PID). setsid() only affects the "process group" and "session" relationships, and not the "parent" relationship.

    On my system, credentials(7) says:
    Sessions and process groups are abstractions devised to support shell
    job control. A process group (sometimes called a "job") is a collec-
    tion of processes that share the same process group ID; the shell cre-
    ates a new process group for the process(es) used to execute single
    command or pipeline (e.g., the two processes created to execute the
    command "ls | wc" are placed in the same process group). A process's
    group membership can be set using setpgid(2). The process whose
    process ID is the same as its process group ID is the process group
    leader for that group.

    A session is a collection of processes that share the same session ID.
    All of the members of a process group also have the same session ID
    (i.e., all of the members of a process group always belong to the same
    session, so that sessions and process groups form a strict two-level
    hierarchy of processes.) A new session is created when a process calls
    setsid(2), which creates a new session whose session ID is the same as
    the PID of the process that called setsid(2). The creator of the ses-
    sion is called the session leader.

    All of the processes in a session share a controlling terminal. The
    controlling terminal is established when the session leader first opens
    a terminal (unless the O_NOCTTY flag is specified when calling
    open(2)). A terminal may be the controlling terminal of at most one
    session.

    At most one of the jobs in a session may be the foreground job; other
    jobs in the session are background jobs. Only the foreground job may
    read from the terminal; when a process in the background attempts to
    read from the terminal, its process group is sent a SIGTTIN signal,
    which suspends the job. If the TOSTOP flag has been set for the termi-
    nal (see termios(3)), then only the foreground job may write to the
    terminal; writes from background job cause a SIGTTOU signal to be gen-
    erated, which suspends the job. When terminal keys that generate a
    signal (such as the interrupt key, normally control-C) are pressed, the
    signal is sent to the processes in the foreground job.

    So, while setsid(2) "creates a session and sets the process group ID" for a process, it does not change the process' parent PID.


    int main()
    {
    printf("Parent pid %d\n",getpid());
    switch(fork())
    {
    case -1:
    perror("fork");
    return 0;
    case 0:
    // child
    break;
    default:
    // Parent
    sleep(1);
    return 0;
    }

    setsid();
    printf("Child parent = %d\n",getppid());
    return 0;
    }

    HTH

    --
    Lew Pitcher
    "In Skills We Trust"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Muttley@DastartdlyHQ.org on Fri Nov 8 17:26:41 2024
    Muttley@DastartdlyHQ.org writes:
    I've tried this code on both MacOS and Linux yet the child process getppid() >still returns its original parent process instead of "1" for init which is >what I'd expect. Isn't setsid() supposed to completely detach the child or >have I misunderstood?

    You only want the child to issue setsid.


    int main()
    {
    printf("Parent pid %d\n",getpid());
    switch(fork())
    {
    case -1:
    perror("fork");
    return 0;
    case 0:

    setsid();

    // child
    break;
    default:
    // Parent
    sleep(1);
    return 0;
    }

    printf("Child parent = %d\n",getppid());
    return 0;
    }


    pid = fork();
    if (pid == (pid_t)-1) {
    pfmt(stderr, MM_ERROR, failed, "fork", Strerror(errno));
    goto dead;
    }
    if (pid == 0) {
    sigchild();
    #ifdef SIGTSTP
    sigset(SIGTSTP, SIG_IGN);
    sigset(SIGTTIN, SIG_IGN);
    sigset(SIGTTOU, SIG_IGN);
    #endif
    signal(SIGHUP,SIG_IGN);
    signal(SIGINT,SIG_IGN);
    signal(SIGQUIT,SIG_IGN);
    #ifdef preSVr4 /* block all tty generated signals from affecting our mailer */
    setpgrp();
    #else
    setsid();
    #endif
    s = fileno(mtf);
    for (i = 3; i < 32; i++)
    if (i != s)
    close(i);
    close(0);
    dup(s);
    close(s);
    if ((deliver = value("sendmail")) == NOSTR)
    deliver = MAIL;
    execvp(safeexpand(deliver), namelist);
    pfmt(stderr, MM_ERROR, errmsg, deliver, Strerror(errno));
    fflush(stderr);
    _exit(1);
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Lew Pitcher on Sat Nov 9 00:07:27 2024
    On Fri, 8 Nov 2024 15:30:21 -0000 (UTC), Lew Pitcher wrote:

    So, while setsid(2) "creates a session and sets the process group ID"
    for a process, it does not change the process' parent PID.

    It is possible for the parent process to terminate before the child.
    The child is then said to be “orphaned”. From this point, normally getppid() will return 1, the PID of the init process.

    However, on Linux, it is possible to specify an alternative “child subreaper” process, via prctl() <https://manpages.debian.org/bookworm/manpages-dev/prctl.2.en.html>.
    getppid() will then return the ID of this process.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kenny McCormack@21:1/5 to Muttley@DastartdlyHQ.org on Sat Nov 9 09:25:22 2024
    In article <vgl8h1$385vs$1@dont-email.me>, <Muttley@DastartdlyHQ.org> wrote: >I've tried this code on both MacOS and Linux yet the child process getppid() >still returns its original parent process instead of "1" for init which is >what I'd expect. Isn't setsid() supposed to completely detach the child or >have I misunderstood?

    I suppose the obvious question at this point is: Why do you care? What's
    the underlying issue?

    I'm not saying that to be snarky (seriously, I'm not!). I am genuinely
    curious as to why you are curious. If this is a solely a question of
    academic curiosity, then the answer is "because that's the way it is". As
    far as I know, in classic Unix, the only way for a process to get
    "re-parented" is to have the parent die. Of course, as others have noted, under Linux, there is also the re-parenting "prctl".

    The usual method for ensuring that a process *does* have getppid() == 1 is
    the classic "double fork". The parent forks(), the child then forks() and exits. The grandchild then does the work (either directly or via exec()).

    BTW, note that "total isolation" (in your words, "completely detach") is actually somewhat difficult to achieve and care must be taken to do it
    right. Among other things, if you have any terminals open (the usual stdin/stdout/stderr), then you still have a connection to those terminals
    and may receive signals therefrom (e.g., if a user hits ^C on that terminal
    or if the terminal is terminated). "sshfs", in particular, is vulnerable
    to this problem; unless you take special care, sshfs will terminate if the shell (terminal window) from which it was launched is exited.

    In fact, it is somewhat surprising how many common ordinary day-to-day
    programs there are that still do things like this. And by "do things like this", I mean fail to daemonize correctly.

    --
    I shot a man on Fifth Aveneue, just to see him die.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)