static void GTK_EndProcessDetector(gpointer data, gint source,
GdkInputCondition WXUNUSED(condition) )
{
- wxEndProcessData *proc_data = (wxEndProcessData *)data;
-
- wxHandleProcessTermination(proc_data);
-
- close(source);
- gdk_input_remove(proc_data->tag);
+ wxEndProcessData *proc_data = (wxEndProcessData *)data;
+ close(source);
+ gdk_input_remove(proc_data->tag);
+
+ // This has to come after gdk_input_remove() or we will
+ // occasionally receive multiple callbacks with corrupt data
+ // pointers. (KB)
+ wxHandleProcessTermination(proc_data);
}
int wxAddProcessCallback(wxEndProcessData *proc_data, int fd)
static void GTK_EndProcessDetector(gpointer data, gint source,
GdkInputCondition WXUNUSED(condition) )
{
- wxEndProcessData *proc_data = (wxEndProcessData *)data;
-
- wxHandleProcessTermination(proc_data);
-
- close(source);
- gdk_input_remove(proc_data->tag);
+ wxEndProcessData *proc_data = (wxEndProcessData *)data;
+ close(source);
+ gdk_input_remove(proc_data->tag);
+
+ // This has to come after gdk_input_remove() or we will
+ // occasionally receive multiple callbacks with corrupt data
+ // pointers. (KB)
+ wxHandleProcessTermination(proc_data);
}
int wxAddProcessCallback(wxEndProcessData *proc_data, int fd)
// systems wait() might be used instead in a loop (until the right pid
// terminates)
int status = 0;
- if ( waitpid(pid, &status, 0) == -1 || !WIFEXITED(status) )
+ int rc;
+
+ do
+ rc = waitpid(pid, &status, 0);
+ while(rc == -1 && ( /* errno == ERESTARTSYS || */ errno == EINTR) );
+ // waitpid() was interrupted, try again
+
+
+ if( rc == -1 || ! (WIFEXITED(status) || WIFSIGNALED(status)) )
{
- wxLogSysError(_("Waiting for subprocess termination failed"));
+ wxLogSysError(_("Waiting for subprocess termination failed"));
+ /* AFAIK, this can only happen if something went wrong within
+ wxGTK, i.e. due to a racecondition or some serious bug.
+ After having fixed the order of statements in
+ GTK_EndProcessDetector(). (KB)
+ */
}
else
{
proc_data->process->OnTerminate(proc_data->pid,
WEXITSTATUS(status));
}
- }
-
- // clean up
- if ( proc_data->pid > 0 )
- {
- delete proc_data;
- }
- else
- {
- // wxExecute() will know about it
- proc_data->exitcode = status;
-
- proc_data->pid = 0;
+ // clean up
+ if ( proc_data->pid > 0 )
+ {
+ delete proc_data;
+ }
+ else
+ {
+ // wxExecute() will know about it
+ proc_data->exitcode = status;
+
+ proc_data->pid = 0;
+ }
}
}
else
{
#if wxUSE_GUI
- // we're in parent
- close(end_proc_detect[1]); // close writing side
-
wxEndProcessData *data = new wxEndProcessData;
- data->tag = wxAddProcessCallback(data, end_proc_detect[0]);
+
ARGS_CLEANUP;
// sync execution: indicate it by negating the pid
data->pid = -pid;
+ data->tag = wxAddProcessCallback(data, end_proc_detect[0]);
+ // we're in parent
+ close(end_proc_detect[1]); // close writing side
// it will be set to 0 from GTK_EndProcessDetector
while (data->pid != 0)
else
{
// async execution, nothing special to do - caller will be
- // notified about the process terminationif process != NULL, data
+ // notified about the process termination if process != NULL, data
// will be deleted in GTK_EndProcessDetector
data->process = process;
data->pid = pid;
+ data->tag = wxAddProcessCallback(data, end_proc_detect[0]);
+ // we're in parent
+ close(end_proc_detect[1]); // close writing side
return pid;
}