git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 1/4] run-command: add new check_command helper

From
Felipe Contreras <felipe.contreras@gmail.com>
Date
Apr 1, 2013, 23:58 UTC
Message-ID
<CAMP44s3NxBexkaQa=KxJ963L29T4BAn7e+-3YVz-vgUp8jrb4A@mail.gmail.com>
In-Reply-To
<20130401232326.GA30935@sigill.intra.peff.net>
On Mon, Apr 1, 2013 at 5:23 PM, Jeff King <peff@peff.net> wrote:
> On Mon, Apr 01, 2013 at 03:46:41PM -0600, Felipe Contreras wrote:
Show 21 quoted lines
>> -static int wait_or_whine(pid_t pid, const char *argv0)
>> +static pid_t persistent_waitpid(struct child_process *cmd, pid_t pid, int *stat_loc)
>> +{
>> +     if (cmd->last_wait.code) {
>> +             errno = cmd->last_wait.failed_errno;
>> +             *stat_loc = cmd->last_wait.status;
>> +             return errno ? -1 : pid;
>> +     } else {
>> +             pid_t waiting;
>> +             while ((waiting = waitpid(pid, stat_loc, 0)) < 0 && errno == EINTR)
>> +                     ;       /* nothing */
>> +             return waiting;
>> +     }
>> +}
>
> So it looks we are trying to save the waitpid state from a previous run
> and use the saved value. Otherwise, waitpid as normal.
>
> We loop on EINTR when we actually call waitpid(). But we don't check
> whether the saved errno is waitpid. What happens if we EINTR during the
> saved call to waitpid?

Are you saying that even if we have stored the result of a waitpid command, if errno is EINTR, then we should still loop waitpid()? If so, I guess this would do the trick:

static pid_t persistent_waitpid(struct child_process *cmd, pid_t pid,
int *stat_loc)
{
	pid_t waiting;
	if (cmd->last_wait.code) {
		errno = cmd->last_wait.failed_errno;
		*stat_loc = cmd->last_wait.status;
		if (errno != EINTR)
			return errno ? -1 : pid;
	}
	while ((waiting = waitpid(pid, stat_loc, 0)) < 0 && errno == EINTR)
		;	/* nothing */
	return waiting;
}
Show 15 quoted lines
>> +static int wait_or_whine(struct child_process *cmd, pid_t pid, const char *argv0)
>>  {
>>       int status, code = -1;
>>       pid_t waiting;
>>       int failed_errno = 0;
>>
>> -     while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
>> -             ;       /* nothing */
>> +     waiting = persistent_waitpid(cmd, pid, &status);
>>
>>       if (waiting < 0) {
>>               failed_errno = errno;
>
> We now take argv0 into wait_or_whine. But I don't see it being used.
> What's it for?

It was there before: -static int wait_or_whine(pid_t pid, const char *argv0) +static int wait_or_whine(struct child_process *cmd, pid_t pid, const char *argv0)

Show 26 quoted lines
>> +int check_command(struct child_process *cmd)
>> +{
>> +     int status;
>> +     pid_t waiting;
>> +     int failed_errno = 0;
>> +
>> +     waiting = waitpid(cmd->pid, &status, WNOHANG);
>
> This might return the pid if it has died, -1 if there was an error, or 0
> if the process still exists but hasn't died. So...
>
>> +     if (waiting != cmd->pid)
>> +             return 1;
>> +
>> +     if (waiting < 0)
>> +             failed_errno = errno;
>
> How would we ever trigger this second conditional? It makes sense to
> return 1 when "waiting == 0", as that is saying "yes, your process is
> still running" (though documenting the return either at the top of the
> function or in the commit message would be helpful)
>
> But if we get an error from waitpid, we would also return 1, which
> doesn't make sense (especially if it is something like EINTR -- I don't
> know offhand if we can get EINTR during WNOHANG. It should not block,
> but I don't know if it can race with a signal).
How about this?
if (waiting >= 0 && waiting != cmd->pid)
		return 1;
Show 5 quoted lines
>> +     cmd->last_wait.code = -1;
>> +     cmd->last_wait.failed_errno = failed_errno;
>> +     cmd->last_wait.status = status;
>
> Since we can only get here when waiting == cmd->pid,
No, also when waiting < 0.
> Why is code set to -1?  It
> seems to be used as a flag to say "this structure is valid". Should it
> be defined as "unsigned valid:1;" instead?
Yeap. I was using it for other purposes before, 'valid' would be better now.
Cheers.
-- 
Felipe Contreras
Previous: Jeff KingNext: Jeff King
Message 4 of 21 in “run-command: new check_command helper”
  1. 0/4 run-command: new check_command helperFelipe Contreras, Apr 1, 2013
  2. 1/4 run-command: add new check_command helperFelipe Contreras, Apr 1, 2013
  3. Jeff KingApr 1, 2013
  4. Felipe ContrerasApr 1, 2013
  5. Jeff KingApr 2, 2013
  6. Felipe ContrerasApr 2, 2013
  7. Jeff KingApr 2, 2013
  8. Felipe ContrerasApr 2, 2013
  9. Jeff KingApr 2, 2013
  10. 2/4 transport-helper: check if remote helper is aliveFelipe Contreras, Apr 1, 2013
  11. Jeff KingApr 1, 2013
  12. Felipe ContrerasApr 2, 2013
  13. Jeff KingApr 2, 2013
  14. Felipe ContrerasApr 2, 2013
  15. Jeff KingApr 2, 2013
  16. Felipe ContrerasApr 2, 2013
  17. Felipe ContrerasApr 2, 2013
  18. Junio C HamanoApr 2, 2013
  19. Felipe ContrerasApr 2, 2013
  20. 3/4 tmp: remote-helper: add timers to catch errorsFelipe Contreras, Apr 1, 2013
  21. 4/4 tmp: run-command: code to exercise check_commandFelipe Contreras, Apr 1, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.