Sysop: | Amessyroom |
---|---|
Location: | Fayetteville, NC |
Users: | 43 |
Nodes: | 6 (0 / 6) |
Uptime: | 94:07:15 |
Calls: | 290 |
Calls today: | 1 |
Files: | 904 |
Messages: | 76,378 |
In article <vgl8h1$385vs$1@dont-email.me>, <Muttley@DastartdlyHQ.org> wrote:[snip]
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?
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()).
On Sat, 09 Nov 2024 09:25:22 +0000, Kenny McCormack wrote:
In article <vgl8h1$385vs$1@dont-email.me>, <Muttley@DastartdlyHQ.org> wrote:[snip]
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?
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
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?
under Linux, there is also the re-parenting "prctl".
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.
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
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".
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."
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"?
can't help thinking they should be a single shot OS call to completely seperate the child from parent.
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.
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?
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.
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?
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.
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".
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
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.
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;
}
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;
}
printf("Child parent = %d\n",getppid());
return 0;
}
So, while setsid(2) "creates a session and sets the process group ID"
for a process, it does not change the process' parent PID.