Fix for waitpid return EINTR sometimes on launch.

The return of EINTR is not exactly a failure of child process but may be because of any number of reasons. Adding logic to retry to get status of child process.

Bug: 10889
Change-Id: Ic2de7248cb7bd9c801b917c841ce911fb7c17dcc
Reviewed-on: https://code.wireshark.org/review/7669
Petri-Dish: Graham Bloice <graham.bloice@trihedral.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Vik 2015-03-12 20:32:48 -07:00 committed by Anders Broman
parent f0855e03d1
commit dc2195711c
1 changed files with 38 additions and 29 deletions

View File

@ -1865,7 +1865,10 @@ static int
sync_pipe_wait_for_child(int fork_child, gchar **msgp)
{
int fork_child_status;
int ret;
#ifndef _WIN32
int retry_waitpid = 3;
#endif
int ret = -1;
GTimeVal start_time;
GTimeVal end_time;
float elapsed;
@ -1898,37 +1901,43 @@ sync_pipe_wait_for_child(int fork_child, gchar **msgp)
}
}
#else
if (waitpid(fork_child, &fork_child_status, 0) != -1) {
if (WIFEXITED(fork_child_status)) {
/*
* The child exited; return its exit status. Do not treat this as
* an error.
*/
ret = WEXITSTATUS(fork_child_status);
} else if (WIFSTOPPED(fork_child_status)) {
/* It stopped, rather than exiting. "Should not happen." */
*msgp = g_strdup_printf("Child dumpcap process stopped: %s",
sync_pipe_signame(WSTOPSIG(fork_child_status)));
ret = -1;
} else if (WIFSIGNALED(fork_child_status)) {
/* It died with a signal. */
*msgp = g_strdup_printf("Child dumpcap process died: %s%s",
sync_pipe_signame(WTERMSIG(fork_child_status)),
WCOREDUMP(fork_child_status) ? " - core dumped" : "");
while (--retry_waitpid >= 0) {
if (waitpid(fork_child, &fork_child_status, 0) != -1) {
if (WIFEXITED(fork_child_status)) {
/*
* The child exited; return its exit status. Do not treat this as
* an error.
*/
ret = WEXITSTATUS(fork_child_status);
} else if (WIFSTOPPED(fork_child_status)) {
/* It stopped, rather than exiting. "Should not happen." */
*msgp = g_strdup_printf("Child dumpcap process stopped: %s",
sync_pipe_signame(WSTOPSIG(fork_child_status)));
ret = -1;
} else if (WIFSIGNALED(fork_child_status)) {
/* It died with a signal. */
*msgp = g_strdup_printf("Child dumpcap process died: %s%s",
sync_pipe_signame(WTERMSIG(fork_child_status)),
WCOREDUMP(fork_child_status) ? " - core dumped" : "");
ret = -1;
} else {
/* What? It had to either have exited, or stopped, or died with
a signal; what happened here? */
*msgp = g_strdup_printf("Bad status from waitpid(): %#o",
fork_child_status);
ret = -1;
}
} else if (errno != ECHILD) {
*msgp = g_strdup_printf("Error from waitpid(): %s", g_strerror(errno));
ret = -1;
} else if (errno == EINTR) {
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_WARNING, "sync_pipe_wait_for_child: waitpid returned EINTR. retrying.");
continue;
} else {
/* What? It had to either have exited, or stopped, or died with
a signal; what happened here? */
*msgp = g_strdup_printf("Bad status from waitpid(): %#o",
fork_child_status);
ret = -1;
/* errno == ECHILD ; echld might have already reaped the child */
ret = fetch_dumpcap_pid ? 0 : -1;
}
} else if (errno != ECHILD) {
*msgp = g_strdup_printf("Error from waitpid(): %s", g_strerror(errno));
ret = -1;
} else {
/* errno == ECHILD ; echld might have already reaped the child */
ret = fetch_dumpcap_pid ? 0 : -1;
break;
}
#endif