Beispiel #1
0
void OnSignalChildHandler(int /*signal*/, siginfo_t *siginfo, void * /*ucontext*/)
{
	// Build the log message
	wxString msg;
	msg << wxT("OnSignalChildHandler() has been called for child process with pid `") <<
		siginfo->si_pid <<
		wxT("'. ");
	// Make sure we leave no zombies by calling waitpid()
	int status = 0;
	pid_t result = AmuleWaitPid(siginfo->si_pid, &status, WNOHANG, &msg);
	if (result != 1 && result != 0 && (WIFEXITED(status) || WIFSIGNALED(status))) {
		// Fetch the wxEndProcessData structure corresponding to this pid
		EndProcessDataMap::iterator it = endProcDataMap.find(siginfo->si_pid);
		if (it != endProcDataMap.end()) {
			wxEndProcessData *endProcData = it->second;
			// Remove this entry from the process map
			endProcDataMap.erase(siginfo->si_pid);
			// Save the exit code for the wxProcess object to read later
			endProcData->exitcode = result != -1 && WIFEXITED(status) ?
				WEXITSTATUS(status) : -1;
			// Make things work as in wxGUI
			wxHandleProcessTermination(endProcData);

			// wxHandleProcessTermination() will "delete endProcData;"
			// So we do not delete it again, ok? Do not uncomment this line.
			//delete endProcData;
		} else {
			msg << wxT(" Error: the child process pid is not on the pid map.");
		}
	}

	// Log our passage here
	AddDebugLogLineN(logGeneral, msg);
}
Beispiel #2
0
static
void GTK_EndProcessDetector(gpointer data, gint source,
                            GdkInputCondition WXUNUSED(condition) )
{
   wxEndProcessData *proc_data = (wxEndProcessData *)data;

   // has the process really terminated? unfortunately GDK (or GLib) seem to
   // generate G_IO_HUP notification even when it simply tries to read from a
   // closed fd and hasn't terminated at all
   int pid = (proc_data->pid > 0) ? proc_data->pid : -(proc_data->pid);
   int status = 0;
   int rc = waitpid(pid, &status, WNOHANG);

   if ( rc == 0 )
   {
       // no, it didn't exit yet, continue waiting
       return;
   }

   // set exit code to -1 if something bad happened
   proc_data->exitcode = rc != -1 && WIFEXITED(status) ? WEXITSTATUS(status)
                                                      : -1;

   // child exited, end waiting
   close(source);

   // don't call us again!
   gdk_input_remove(proc_data->tag);

   wxHandleProcessTermination(proc_data);
}
Beispiel #3
0
        virtual void OnReadWaiting()
        {
            wxFDIODispatcher::Get()->UnregisterFD(m_fd);
            close(m_fd);

            wxHandleProcessTermination(m_data);

            delete this;
        }
Beispiel #4
0
/*!
    Called due to source signal detected by the CFRunLoop.
    This is nearly identical to the wxGTK equivalent.
 */
extern "C" void WXCF_EndProcessDetector(CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, void const *data, void *info)
{
    wxEndProcessData * const proc_data = static_cast<wxEndProcessData*>(info);

/// This code could reasonably be shared between wxMac/wxCocoa and wxGTK ///
    // PID is always positive on UNIX but wx uses the sign bit as a flag.
    int pid = (proc_data->pid > 0) ? proc_data->pid : -proc_data->pid;
    int status = 0;
    int rc = waitpid(pid, &status, WNOHANG);
    if(rc == 0)
    {
        // Keep waiting in case we got a spurious notification
        // NOTE: In my limited testing, this doesn't happen.
        return;
    }

    if(rc == -1)
    {   // Error.. really shouldn't happen but try to gracefully handle it
        wxLogLastError(_T("waitpid"));
        proc_data->exitcode = -1;
    }
    else
    {   // Process ended for some reason
        wxASSERT_MSG(rc == pid, _T("unexpected waitpid() return value"));

        if(WIFEXITED(status))
            proc_data->exitcode = WEXITSTATUS(status);
        else if(WIFSIGNALED(status))
            // wxGTK doesn't do this but why not?
            proc_data->exitcode = -WTERMSIG(status);
        else
        {   // Should NEVER happen according to waitpid docs
            wxLogError(wxT("waitpid indicates process exited but not due to exiting or signalling"));
            proc_data->exitcode = -1;
        }
    }
/// The above code could reasonably be shared between wxMac/wxCocoa and wxGTK ///

    /*
        Either waitpid failed or the process ended successfully.  Either way,
        we're done.  It's not if waitpid is going to magically succeed when
        we get fired again.  CFSocketInvalidate closes the fd for us and also
        invalidates the run loop source for us which should cause it to
        release the CFSocket (thus causing it to be deallocated) and remove
        itself from the runloop which should release it and cause it to also
        be deallocated.  Of course, it's possible the RunLoop hangs onto
        one or both of them by retaining/releasing them within its stack
        frame.  However, that shouldn't be depended on.  Assume that s is
        deallocated due to the following call.
     */
    CFSocketInvalidate(s);

    // Now tell wx that the process has ended.
    wxHandleProcessTermination(proc_data);
}
Beispiel #5
0
static void xt_notify_end_process(XtPointer data, int *WXUNUSED(fid),
                                  XtInputId *id)
{
    wxEndProcessData *proc_data = (wxEndProcessData *)data;

    wxHandleProcessTermination(proc_data);

    // VZ: I think they should be the same...
    wxASSERT( (int)*id == proc_data->tag );

    XtRemoveInput(*id);
}
Beispiel #6
0
static gboolean EndProcessDetector(GIOChannel* source, GIOCondition, void* data)
{
    wxEndProcessData * const
        proc_data = static_cast<wxEndProcessData *>(data);

    // child exited, end waiting
    close(g_io_channel_unix_get_fd(source));

    wxHandleProcessTermination(proc_data);

    // don't call us again!
    return false;
}
Beispiel #7
0
    void OnTerminate(wxProcessEvent& event)
    {
        Disconnect(-1, wxEVT_END_PROCESS, wxProcessEventHandler(wxProcessTerminationEventHandler::OnTerminate));
        wxHandleProcessTermination(m_data);

        // NOTE: We don't use this to delay destruction until the next idle run but rather to
        // avoid killing ourselves while our caller (which is our wxEvtHandler superclass
        // ProcessPendingEvents) still needs our m_eventsLocker to be valid.
        // Since we're in the GUI library we can guarantee that ScheduleForDestroy is using
        // the GUI implementation which delays destruction and not the base implementation
        // which does it immediately.
        wxTheApp->GetTraits()->ScheduleForDestroy(this);
    }
static
void GTK_EndProcessDetector(gpointer data, gint source,
                            GdkInputCondition WXUNUSED(condition))
{
    wxEndProcessData * const
        proc_data = static_cast<wxEndProcessData *>(data);

    // child exited, end waiting
    close(source);

    // don't call us again!
    gdk_input_remove(proc_data->tag);

    wxHandleProcessTermination(proc_data);
}
Beispiel #9
0
void wxMAC_MachPortEndProcessDetect(CFMachPortRef port, void *data)
{
    wxEndProcessData *proc_data = (wxEndProcessData*)data;
    wxLogDebug(wxT("Process ended"));
    int status = 0;
    int rc = waitpid(abs(proc_data->pid), &status, WNOHANG);
    if(!rc)
    {
        wxLogDebug(wxT("Mach port was invalidated, but process hasn't terminated!"));
        return;
    }
    if((rc != -1) && WIFEXITED(status))
        proc_data->exitcode = WEXITSTATUS(status);
    else
        proc_data->exitcode = -1;
    wxHandleProcessTermination(proc_data);
}
/*!
    Called due to source signal detected by the CFRunLoop.
    This is nearly identical to the wxGTK equivalent.
 */
extern "C" void WXCF_EndProcessDetector(CFSocketRef s,
                                        CFSocketCallBackType WXUNUSED(callbackType),
                                        CFDataRef WXUNUSED(address),
                                        void const *WXUNUSED(data),
                                        void *info)
{
    /*
        Either our pipe was closed or the process ended successfully.  Either way,
        we're done.  It's not if waitpid is going to magically succeed when
        we get fired again.  CFSocketInvalidate closes the fd for us and also
        invalidates the run loop source for us which should cause it to
        release the CFSocket (thus causing it to be deallocated) and remove
        itself from the runloop which should release it and cause it to also
        be deallocated.  Of course, it's possible the RunLoop hangs onto
        one or both of them by retaining/releasing them within its stack
        frame.  However, that shouldn't be depended on.  Assume that s is
        deallocated due to the following call.
     */
    CFSocketInvalidate(s);

    // Now tell wx that the process has ended.
    wxHandleProcessTermination(static_cast<wxEndProcessData *>(info));
}
Beispiel #11
0
void wxCheckForFinishedChildren()
{
    wxProcMap::iterator it;
    if (!gs_procmap) return;
    if (gs_procmap->size() == 0) {
      // Map empty, delete it.
      delete gs_procmap;
      gs_procmap = NULL;
      return;
    }
    for (it = gs_procmap->begin();it != gs_procmap->end(); ++it)
    {
        wxEndProcessData *proc_data = it->second;
        int pid = (proc_data->pid > 0) ? proc_data->pid : -(proc_data->pid);
        int status = 0;
        // has the process really terminated?
        int rc = waitpid(pid, &status, WNOHANG);
        if (rc == 0)
            continue;       // no, it didn't exit yet, continue waiting

        // set exit code to -1 if something bad happened
        proc_data->exitcode = rc != -1 && WIFEXITED(status) ?
                   WEXITSTATUS(status) : -1;

        // child exited, end waiting
        close(it->first);

        // don't call us again!
        gs_procmap->erase(it->first);

        wxHandleProcessTermination(proc_data);

        // Iterator is invalid. Handle any further children in subsequent
        // calls.
        break;
    }
}