+
+bool wxHandleFatalExceptions(bool doit)
+{
+ // old sig handlers
+ static bool s_savedHandlers = false;
+ static struct sigaction s_handlerFPE,
+ s_handlerILL,
+ s_handlerBUS,
+ s_handlerSEGV;
+
+ bool ok = true;
+ if ( doit && !s_savedHandlers )
+ {
+ // install the signal handler
+ struct sigaction act;
+
+ // some systems extend it with non std fields, so zero everything
+ memset(&act, 0, sizeof(act));
+
+ act.sa_handler = wxFatalSignalHandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+
+ ok &= sigaction(SIGFPE, &act, &s_handlerFPE) == 0;
+ ok &= sigaction(SIGILL, &act, &s_handlerILL) == 0;
+ ok &= sigaction(SIGBUS, &act, &s_handlerBUS) == 0;
+ ok &= sigaction(SIGSEGV, &act, &s_handlerSEGV) == 0;
+ if ( !ok )
+ {
+ wxLogDebug(_T("Failed to install our signal handler."));
+ }
+
+ s_savedHandlers = true;
+ }
+ else if ( s_savedHandlers )
+ {
+ // uninstall the signal handler
+ ok &= sigaction(SIGFPE, &s_handlerFPE, NULL) == 0;
+ ok &= sigaction(SIGILL, &s_handlerILL, NULL) == 0;
+ ok &= sigaction(SIGBUS, &s_handlerBUS, NULL) == 0;
+ ok &= sigaction(SIGSEGV, &s_handlerSEGV, NULL) == 0;
+ if ( !ok )
+ {
+ wxLogDebug(_T("Failed to uninstall our signal handler."));
+ }
+
+ s_savedHandlers = false;
+ }
+ //else: nothing to do
+
+ return ok;
+}
+
+#endif // wxUSE_ON_FATAL_EXCEPTION
+
+#endif // wxUSE_BASE
+
+#if wxUSE_GUI
+
+// ----------------------------------------------------------------------------
+// wxExecute support
+// ----------------------------------------------------------------------------
+
+// Darwin doesn't use the same process end detection mechanisms so we don't
+// need wxExecute-related helpers for it
+#if !(defined(__DARWIN__) && defined(__WXMAC__))
+
+bool wxGUIAppTraits::CreateEndProcessPipe(wxExecuteData& execData)
+{
+ return execData.pipeEndProcDetect.Create();
+}
+
+bool wxGUIAppTraits::IsWriteFDOfEndProcessPipe(wxExecuteData& execData, int fd)
+{
+ return fd == (execData.pipeEndProcDetect)[wxPipe::Write];
+}
+
+void wxGUIAppTraits::DetachWriteFDOfEndProcessPipe(wxExecuteData& execData)
+{
+ execData.pipeEndProcDetect.Detach(wxPipe::Write);
+ execData.pipeEndProcDetect.Close();
+}
+
+#else // !Darwin
+
+bool wxGUIAppTraits::CreateEndProcessPipe(wxExecuteData& WXUNUSED(execData))
+{
+ return true;
+}
+
+bool
+wxGUIAppTraits::IsWriteFDOfEndProcessPipe(wxExecuteData& WXUNUSED(execData),
+ int WXUNUSED(fd))
+{
+ return false;
+}
+
+void
+wxGUIAppTraits::DetachWriteFDOfEndProcessPipe(wxExecuteData& WXUNUSED(execData))
+{
+ // nothing to do here, we don't use the pipe
+}
+
+#endif // !Darwin/Darwin
+
+int wxGUIAppTraits::WaitForChild(wxExecuteData& execData)
+{
+ wxEndProcessData *endProcData = new wxEndProcessData;
+
+ const int flags = execData.flags;
+
+ // wxAddProcessCallback is now (with DARWIN) allowed to call the
+ // callback function directly if the process terminates before
+ // the callback can be added to the run loop. Set up the endProcData.
+ if ( flags & wxEXEC_SYNC )
+ {
+ // we may have process for capturing the program output, but it's
+ // not used in wxEndProcessData in the case of sync execution
+ endProcData->process = NULL;
+
+ // sync execution: indicate it by negating the pid
+ endProcData->pid = -execData.pid;
+ }
+ else
+ {
+ // async execution, nothing special to do -- caller will be
+ // notified about the process termination if process != NULL, endProcData
+ // will be deleted in GTK_EndProcessDetector
+ endProcData->process = execData.process;
+ endProcData->pid = execData.pid;
+ }
+
+
+ if ( !(flags & wxEXEC_NOEVENTS) )
+ {
+#if defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__))
+ endProcData->tag = wxAddProcessCallbackForPid(endProcData, execData.pid);
+#else
+ endProcData->tag = wxAddProcessCallback
+ (
+ endProcData,
+ execData.pipeEndProcDetect.Detach(wxPipe::Read)
+ );
+
+ execData.pipeEndProcDetect.Close();
+#endif // defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__))
+ }
+
+ if ( flags & wxEXEC_SYNC )
+ {
+ wxBusyCursor bc;
+ int exitcode = 0;
+
+ wxWindowDisabler *wd = flags & (wxEXEC_NODISABLE | wxEXEC_NOEVENTS)
+ ? NULL
+ : new wxWindowDisabler;
+
+ if ( flags & wxEXEC_NOEVENTS )
+ {
+ // just block waiting for the child to exit
+ int status = 0;
+
+ int result = waitpid(execData.pid, &status, 0);
+
+ if ( result == -1 )
+ {
+ wxLogLastError(_T("waitpid"));
+ exitcode = -1;
+ }
+ else
+ {
+ wxASSERT_MSG( result == execData.pid,
+ _T("unexpected waitpid() return value") );
+
+ if ( WIFEXITED(status) )
+ {
+ exitcode = WEXITSTATUS(status);
+ }
+ else // abnormal termination?
+ {
+ wxASSERT_MSG( WIFSIGNALED(status),
+ _T("unexpected child wait status") );
+ exitcode = -1;
+ }
+ }
+ }
+ else // !wxEXEC_NOEVENTS
+ {
+ // endProcData->pid will be set to 0 from GTK_EndProcessDetector when the
+ // process terminates
+ while ( endProcData->pid != 0 )
+ {
+ bool idle = true;
+
+#if HAS_PIPE_INPUT_STREAM
+ if ( execData.bufOut )
+ {
+ execData.bufOut->Update();
+ idle = false;
+ }
+
+ if ( execData.bufErr )
+ {
+ execData.bufErr->Update();
+ idle = false;
+ }
+#endif // HAS_PIPE_INPUT_STREAM
+
+ // don't consume 100% of the CPU while we're sitting in this
+ // loop
+ if ( idle )
+ wxMilliSleep(1);
+
+ // give GTK+ a chance to call GTK_EndProcessDetector here and
+ // also repaint the GUI
+ wxYield();
+ }
+
+ exitcode = endProcData->exitcode;
+ }
+
+ delete wd;
+ delete endProcData;
+
+ return exitcode;
+ }
+ else // async execution
+ {
+ return execData.pid;
+ }
+}
+
+#endif // wxUSE_GUI
+#if wxUSE_BASE
+
+void wxHandleProcessTermination(wxEndProcessData *proc_data)
+{
+ // notify user about termination if required
+ if ( proc_data->process )
+ {
+ proc_data->process->OnTerminate(proc_data->pid, proc_data->exitcode);
+ }
+
+ // clean up
+ if ( proc_data->pid > 0 )
+ {
+ delete proc_data;
+ }
+ else
+ {
+ // let wxExecute() know that the process has terminated
+ proc_data->pid = 0;
+ }
+}
+
+#endif // wxUSE_BASE