linux-c-programming.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Eric <eric@cisu.net>
To: Glynn Clements <glynn.clements@virgin.net>
Cc: linux-c-programming@vger.kernel.org
Subject: Re: PID's of processes and waiting.
Date: Tue, 22 Jun 2004 22:49:32 -0500	[thread overview]
Message-ID: <200406222249.32523.eric@cisu.net> (raw)
In-Reply-To: <16600.63133.431912.483989@cerise.nosuchdomain.co.uk>

On Tuesday 22 June 2004 10:18 pm, Glynn Clements wrote:
> Eric wrote:
> > 	I am looking for a way to wait for a process to terminate. I have a
> > process that was executed via system() and am getting its PID from a file
> > it writes itself. I have a few questions.
> >
> > 	1. Is it possible to directly get the PID of a processes executed via
> > system()? I do not believe so that is why I am falling back to reading
> > its file.
>
> No.
>
> > 	2. I have tried to waitpid() on the process by giving waitpid the PID
> > read from the file as an argument, however it seems to return immidietly
> > because I assume the new process is not a child of the calling process.
> > Is it in fact a child of the calling process or am I abusing the
> > systemcall? I assume a child is created only via fork()/exec() varients
> > and this is the reason waitpid() is not working.
>
> system("<command>") creates a child process with fork(), then the
> child process exec()s "/bin/sh -c <command>".
>
> Whether or not the process which is actually running the command is a
> child of the process which calls system() depends upon the exact
> command, and possibly upon the implementation of /bin/sh.
>
> Brief experimentation (where /bin/sh is bash-1.x) indicates that, for
> a simple command, it is a child process.

Yes I knew that.

> OTOH, if the command is run in the background (e.g. system("foo &")),
> it won't be a child process (the child process fork()s and exit()s,
> with the grandchild process running the program). Similarly, for a
> sequence of commands (separated by ";"), or a pipeline, the child will
> be the shell with the actual commands being run in grandchild
> processes.

Ahh....so this is what I wanted to know. My process would be a grandparent so 
has little/no control. I kinda thought this, but wasn't 100% sure.

> Essentially, in order for the command to be run as a (direct) child of
> the process which called system(), the shell has to be able to exec()
> the command (as with the shell's "exec" built-in). This can only be
> done for a simple command; no sequences, pipelines, subshells,
> background commands etc.
>
> > 	3. Is waiting to see when the /proc/PID directory disappears a reliable
> > solution? Does this directory die on exit() and is handled by the kernel,
> > or is this unreliable for one reason or another?
>
> At a theoretical level:
>
> 1. /proc may not be mounted (although, as an ever-increasing amount of
> software won't work without it, this is probably a remote possibility
> nowadays).

	True. Reason #1 I knew it was shaky.
> 2. The process could die and the PID could be re-used between checks.

	Very true. I wanted to avoid this at all costs.

> On a more practical level, polling is best avoided where possible, as
> it consumes CPU time. If you poll frequently, it may use a lot of CPU
> time; if you poll less frequently, you introduce delays.

Thats an excellent tip and will surely enhance my programming-to-come. Thank 
you. I was starting to see the delay/cost tradeoff as I spun on checking 
termination by open()/close() the PID file and checking open()'s exit status.

> > 	I am aware that a race/deadlock may occur if a new process takes the PID
> > of the old process I am waiting for in between the time I poll the
> > directory, however, I am at a complete loss on how to wait on this
> > process. I need a reliable indicator that the process has stopped wether
> > gracefully or dying a horrible death. Currently I am polling its PID
> > file...but that is VERY unreliable because it is not cleaned up on a
> > SIGKILL.
> >
> > Does anyone have any ideas?
>
> In general, don't use system(). It's convenient for quick hacks, but
> like most things which are convenient for quick hacks (e.g. scripting
> languages), it makes it easy to write code which sorta-kinda-works,
> but is useless for writing code which works the way it ought to.
>
> Any non-trivial program which needs to spawn subprocesses should do
> the fork+exec+<whatever else> itself.

My program has definatly grown beyond non-trivial.

> OTOH, if it's inevitable that the process in question won't actually
> be a child of the process which initiates it (e.g. because the
> subprocess will be a daemon which needs to perform a second fork to
> detach itself from the session), it would probably be better to
> implement an explicit signalling mechanism, e.g. a pipe, socket, lock
> etc.

> The simplest mechanisms involve having the child hold a resource which
> will be released automatically (by the kernel) upon termination, and
> whose release the parent can detect.
>
> Using a pipe wouldn't require any dedicated code in the child. If the
> parent creates a pipe with the child inheriting the write end and the
> parent performing a blocking read on the other end, the parent will
> get EOF when there are no longer any writers, i.e. when the child (and
> any descendents) have died.
>
> An exclusive file lock is another option. If the child obtains a lock,
> and the parent makes a blocking attempt to obtain a conflicting lock,
> the parent will block until the child releases it (which will happen
> automatically if it dies). This has the advantage that it doesn't
> matter if the child spawns children of its own, as locks aren't
> inherited across a fork(),

Thank you. You gave an excellent response and convinced me that I need a more 
explicit way of controlling my subprocesses activity. I could see this to a 
point, but without more experience, I wasn't sure of all the different 
approaches I could take. 

  reply	other threads:[~2004-06-23  3:49 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-06-23  1:50 PID's of processes and waiting Eric
2004-06-23  3:18 ` Glynn Clements
2004-06-23  3:49   ` Eric [this message]
2004-06-23 15:52 ` Michael Scondo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200406222249.32523.eric@cisu.net \
    --to=eric@cisu.net \
    --cc=glynn.clements@virgin.net \
    --cc=linux-c-programming@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).