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) sync_pipe_wait_for_child(int fork_child, gchar **msgp)
{ {
int fork_child_status; int fork_child_status;
int ret; #ifndef _WIN32
int retry_waitpid = 3;
#endif
int ret = -1;
GTimeVal start_time; GTimeVal start_time;
GTimeVal end_time; GTimeVal end_time;
float elapsed; float elapsed;
@ -1898,37 +1901,43 @@ sync_pipe_wait_for_child(int fork_child, gchar **msgp)
} }
} }
#else #else
if (waitpid(fork_child, &fork_child_status, 0) != -1) { while (--retry_waitpid >= 0) {
if (WIFEXITED(fork_child_status)) { 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. * 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)) { ret = WEXITSTATUS(fork_child_status);
/* It stopped, rather than exiting. "Should not happen." */ } else if (WIFSTOPPED(fork_child_status)) {
*msgp = g_strdup_printf("Child dumpcap process stopped: %s", /* It stopped, rather than exiting. "Should not happen." */
sync_pipe_signame(WSTOPSIG(fork_child_status))); *msgp = g_strdup_printf("Child dumpcap process stopped: %s",
ret = -1; sync_pipe_signame(WSTOPSIG(fork_child_status)));
} else if (WIFSIGNALED(fork_child_status)) { ret = -1;
/* It died with a signal. */ } else if (WIFSIGNALED(fork_child_status)) {
*msgp = g_strdup_printf("Child dumpcap process died: %s%s", /* It died with a signal. */
sync_pipe_signame(WTERMSIG(fork_child_status)), *msgp = g_strdup_printf("Child dumpcap process died: %s%s",
WCOREDUMP(fork_child_status) ? " - core dumped" : ""); 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; 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 { } else {
/* What? It had to either have exited, or stopped, or died with /* errno == ECHILD ; echld might have already reaped the child */
a signal; what happened here? */ ret = fetch_dumpcap_pid ? 0 : -1;
*msgp = g_strdup_printf("Bad status from waitpid(): %#o",
fork_child_status);
ret = -1;
} }
} else if (errno != ECHILD) { break;
*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;
} }
#endif #endif