]> git.saurik.com Git - wxWidgets.git/commitdiff
wxProcess fixes (Detach() added), cleared/corrected wxExecute() documentation
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 17 Feb 1999 17:56:59 +0000 (17:56 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 17 Feb 1999 17:56:59 +0000 (17:56 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1709 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/latex/wx/function.tex
docs/latex/wx/process.tex
include/wx/process.h
src/common/process.cpp
src/gtk/utilsgtk.cpp
src/gtk1/utilsgtk.cpp

index 655af485a748d92b5390771d766d2dc564a6a7ed..d4888be1db3db647e3bdae4c71b65e8442f30ebd 100644 (file)
@@ -946,11 +946,12 @@ arguments, terminated by NULL.
 If {\it sync} is FALSE (the default), flow of control immediately returns.
 If TRUE, the current application waits until the other program has terminated.
 
 If {\it sync} is FALSE (the default), flow of control immediately returns.
 If TRUE, the current application waits until the other program has terminated.
 
-If execution is asynchronous, the return value is the process id,
-otherwise it is a status value.  A zero value indicates that the command could not
-be executed.
+The return value is the process id, not the exit code of invoked program (for
+this you should use wxProcess). A zero value indicates that the command could
+not be executed.
 
 
-If callback isn't NULL and if execution is asynchronous, 
+If callback isn't NULL and if execution is asynchronous (note that callback
+parameter can not be non NULL for synchronous execution), 
 \helpref{wxProcess::OnTerminate}{wxprocessonterminate} will be called when
 the process finishes.
 
 \helpref{wxProcess::OnTerminate}{wxprocessonterminate} will be called when
 the process finishes.
 
index b09bb386efc89670ac92ef50f48f3ce415c9cd86..6d4ba8232ce49317452bc0195c1b94ccf5a26340 100644 (file)
@@ -1,8 +1,18 @@
 \section{\class{wxProcess}}\label{wxprocess}
 
 \section{\class{wxProcess}}\label{wxprocess}
 
-This class contains a method which is invoked when a process finishes.
-It can raise a \helpref{wxProcessEvent}{wxprocessevent} if wxProcess::OnTerminate
-isn't overriden.
+The objects of this class are used in conjonction with 
+\helpref{wxExecute}{wxexecute} function. When a wxProcess object is passed to
+wxExecute(), its \helpref{OnTerminate()}{wxprocessonterminate} virtual method
+is called when the process terminates. This allows the program to be
+(asynchronously) notified about the process termination and also retrieve its
+exit status which is unavailable from wxExecute() in the case of
+asynchronous execution.
+
+Please note that if the process termination notification is processed by the
+parent, it is responsible for deleting the wxProcess object which sent it.
+However, if it is not processed, the object will delete itself and so the
+library users should only delete those objects whose notifications have been
+processed (and call \helpref{Detach()}{wxprocessdetach} for others).
 
 \wxheading{Derived from}
 
 
 \wxheading{Derived from}
 
@@ -22,6 +32,10 @@ Constructs a process object. {\it id} is only used in the case you want to
 use wxWindows events. It identifies this object, or another window that will
 receive the event.
 
 use wxWindows events. It identifies this object, or another window that will
 receive the event.
 
+If the {\it parent} parameter is different from NULL, it will receive
+a wxEVT\_END\_PROCESS notification event (you should insert EVT\_END\_PROCESS
+macro in the event table of the parent to handle it) with the given {\it id}.
+
 \wxheading{Parameters}
 
 \docparam{parent}{The event handler parent.}
 \wxheading{Parameters}
 
 \docparam{parent}{The event handler parent.}
@@ -34,12 +48,28 @@ receive the event.
 
 Destroys the wxProcess object.
 
 
 Destroys the wxProcess object.
 
+\membersection{wxProcess::Detach}\label{wxprocessdetach}
+
+\func{void}{Detach}{\void}
+
+Normally, a wxProcess object is deleted by its parent when it receives the
+notification about the process termination. However, it might happen that the
+parent object is destroyed before the external process is terminated (e.g. a
+window from which this external process was launched is closed by the user)
+and in this case it {\bf should not delete} the wxProcess object, but 
+{\bf should call Detach()} instead. After the wxProcess object is detached
+from its parent, no notification events will be sent to the parent and the
+object will delete itself upon reception of the process termination
+notification.
+
 \membersection{wxProcess::OnTerminate}\label{wxprocessonterminate}
 
 \membersection{wxProcess::OnTerminate}\label{wxprocessonterminate}
 
-\constfunc{void}{OnTerminate}{\param{int}{ pid}}
+\constfunc{void}{OnTerminate}{\param{int}{ pid}, \param{int}{ status}}
 
 It is called when the process with the pid {\it pid} finishes.
 It raises a wxWindows event when it isn't overriden.
 
 
 It is called when the process with the pid {\it pid} finishes.
 It raises a wxWindows event when it isn't overriden.
 
-\docparam{pid}{The pid of the process which ends.}
+\docparam{pid}{The pid of the process which has just terminated.}
+
+\docparam{status}{The exit code of the process.}
 
 
index dc4d5a43a9c94efe3e20246a47de0a76c8ce66d4..b612306a661a2c313f557da3c16fe4547860af19 100644 (file)
@@ -2,11 +2,11 @@
 // Name:        process.h
 // Purpose:     wxProcess class
 // Author:      Guilhem Lavaux
 // Name:        process.h
 // Purpose:     wxProcess class
 // Author:      Guilhem Lavaux
-// Modified by:
+// Modified by: Vadim Zeitlin to check error codes, added Detach() method
 // Created:     24/06/98
 // RCS-ID:      $Id$
 // Copyright:   (c) 1998 Guilhem Lavaux
 // Created:     24/06/98
 // RCS-ID:      $Id$
 // Copyright:   (c) 1998 Guilhem Lavaux
-// Licence:    wxWindows license
+// Licence:     wxWindows license
 /////////////////////////////////////////////////////////////////////////////
 
 #ifndef _WX_PROCESSH__
 /////////////////////////////////////////////////////////////////////////////
 
 #ifndef _WX_PROCESSH__
@@ -55,6 +55,10 @@ public:
 
     virtual void OnTerminate(int pid, int status);
 
 
     virtual void OnTerminate(int pid, int status);
 
+    // detach from the parent - should be called by the parent if it's deleted
+    // before the process it started terminates
+    void Detach();
+
 protected:
     int m_id;
 };
 protected:
     int m_id;
 };
index 2469953ed217308c06411ceea0fc4fe7db0cd7e7..6440993d20363b7011338c325bab4888058e00ec 100644 (file)
@@ -2,11 +2,11 @@
 // Name:        process.cpp
 // Purpose:     Process termination classes
 // Author:      Guilhem Lavaux
 // Name:        process.cpp
 // Purpose:     Process termination classes
 // Author:      Guilhem Lavaux
-// Modified by:
+// Modified by: Vadim Zeitlin to check error codes, added Detach() method
 // Created:     24/06/98
 // RCS-ID:      $Id$
 // Copyright:   (c) Guilhem Lavaux
 // Created:     24/06/98
 // RCS-ID:      $Id$
 // Copyright:   (c) Guilhem Lavaux
-// Licence:    wxWindows license
+// Licence:     wxWindows license
 /////////////////////////////////////////////////////////////////////////////
 
 #ifdef __GNUG__
 /////////////////////////////////////////////////////////////////////////////
 
 #ifdef __GNUG__
@@ -31,15 +31,23 @@ IMPLEMENT_DYNAMIC_CLASS(wxProcessEvent, wxEvent)
 
 wxProcess::wxProcess(wxEvtHandler *parent, int id)
 {
 
 wxProcess::wxProcess(wxEvtHandler *parent, int id)
 {
-  if (parent)
-    SetNextHandler(parent);
+    if (parent)
+        SetNextHandler(parent);
 
 
-  m_id = id;
+    m_id = id;
 }
 
 void wxProcess::OnTerminate(int pid, int status)
 {
 }
 
 void wxProcess::OnTerminate(int pid, int status)
 {
-  wxProcessEvent event(m_id, pid, status);
+    wxProcessEvent event(m_id, pid, status);
 
 
-  ProcessEvent(event);
+    if ( !ProcessEvent(event) )
+        delete this;
+    //else: the object which processed the event is responsible for deleting
+    //      us!
+}
+
+void wxProcess::Detach()
+{
+    SetNextHandler(NULL);
 }
 }
index ba3988e15479b2fabbb1d0fdf3240d4d1c35c6df..fd92f99ba4f94581f47e3aa072a38b316496630b 100644 (file)
@@ -96,7 +96,7 @@ int wxGetOsVersion(int *majorVsn, int *minorVsn)
 {
   if (majorVsn) *majorVsn = GTK_MAJOR_VERSION;
   if (minorVsn) *minorVsn = GTK_MINOR_VERSION;
 {
   if (majorVsn) *majorVsn = GTK_MAJOR_VERSION;
   if (minorVsn) *minorVsn = GTK_MINOR_VERSION;
-  
+
   return wxGTK;
 }
 
   return wxGTK;
 }
 
@@ -123,11 +123,11 @@ char *wxGetUserHome( const wxString &user )
        {
             return ptr;
        }
        {
             return ptr;
        }
-        if ((ptr = getenv("USER")) != NULL || (ptr = getenv("LOGNAME")) != NULL) 
+        if ((ptr = getenv("USER")) != NULL || (ptr = getenv("LOGNAME")) != NULL)
        {
             who = getpwnam(ptr);
         }
        {
             who = getpwnam(ptr);
         }
-       
+
         /* We now make sure the the user exists! */
         if (who == NULL)
        {
         /* We now make sure the the user exists! */
         if (who == NULL)
        {
@@ -299,10 +299,10 @@ long wxExecute( char **argv, bool sync, wxProcess *process )
     wxCHECK_MSG( *argv, 0, "can't exec empty command" );
 
     /* Create pipes */
     wxCHECK_MSG( *argv, 0, "can't exec empty command" );
 
     /* Create pipes */
-    if (pipe(end_proc_detect) == -1) 
+    if (pipe(end_proc_detect) == -1)
     {
     {
-      wxLogSysError( "Pipe creation failed" );
-      return 0;
+        wxLogSysError( "Pipe creation failed" );
+        return 0;
     }
 
     /* fork the process */
     }
 
     /* fork the process */
@@ -311,65 +311,68 @@ long wxExecute( char **argv, bool sync, wxProcess *process )
 #else
     pid_t pid = fork();
 #endif
 #else
     pid_t pid = fork();
 #endif
-    if (pid == -1) 
+    if (pid == -1)
     {
         wxLogSysError( "Fork failed" );
         return 0;
     }
     {
         wxLogSysError( "Fork failed" );
         return 0;
     }
-    else if (pid == 0) 
+    else if (pid == 0)
     {
         // we're in child
         close(end_proc_detect[0]); // close reading side
     {
         // we're in child
         close(end_proc_detect[0]); // close reading side
-       // These three lines close the open file descriptors to
-       // to avoid any input/output which might block the process
-       // or irritate the user. If one wants proper IO for the sub-
-       // process, the "right thing to do" is to start an xterm executing
-       // it.
-       close(STDIN_FILENO);
-       close(STDOUT_FILENO);
-       close(STDERR_FILENO);
+
+        // These three lines close the open file descriptors to
+        // to avoid any input/output which might block the process
+        // or irritate the user. If one wants proper IO for the sub-
+        // process, the "right thing to do" is to start an xterm executing
+        // it.
+        close(STDIN_FILENO);
+        close(STDOUT_FILENO);
+        close(STDERR_FILENO);
+
         // some programs complain about sterr not being open, so
         // redirect them:
         open("/dev/null", O_RDONLY);  // stdin
         // some programs complain about sterr not being open, so
         // redirect them:
         open("/dev/null", O_RDONLY);  // stdin
-       open("/dev/null", O_WRONLY);  // stdout
-       open("/dev/null", O_WRONLY);  // stderr
-        
+        open("/dev/null", O_WRONLY);  // stdout
+        open("/dev/null", O_WRONLY);  // stderr
+
 
 #ifdef _AIX
         execvp ((const char *)*argv, (const char **)argv);
 #else
         execvp (*argv, argv);
 #endif
 
 #ifdef _AIX
         execvp ((const char *)*argv, (const char **)argv);
 #else
         execvp (*argv, argv);
 #endif
+
         // there is no return after successful exec()
         wxLogSysError( "Can't execute '%s'", *argv);
 
         _exit(-1);
     }
         // there is no return after successful exec()
         wxLogSysError( "Can't execute '%s'", *argv);
 
         _exit(-1);
     }
-    else 
+    else
     {
     {
-      // we're in parent
-      close(end_proc_detect[1]); // close writing side
-      data->tag = gdk_input_add(end_proc_detect[0], GDK_INPUT_READ,
-                                GTK_EndProcessDetector, (gpointer)data);
-      data->pid = pid;
-      if (!sync) 
-      {
-        data->process = process;
-      }
-      else 
-      {
-        data->process = (wxProcess *) NULL;
-        data->pid = -(data->pid);
-
-        while (data->pid != 0)
-          wxYield();
-
-        delete data;
-      }
-
-      // @@@ our return value indicates success even if execvp() in the child
-      //     failed!
-      return pid;
+        // we're in parent
+        close(end_proc_detect[1]); // close writing side
+        data->tag = gdk_input_add(end_proc_detect[0], GDK_INPUT_READ,
+                GTK_EndProcessDetector, (gpointer)data);
+        data->pid = pid;
+        if (!sync)
+        {
+            data->process = process;
+        }
+        else
+        {
+            data->process = (wxProcess *) NULL;
+            data->pid = -(data->pid);
+
+            while (data->pid != 0)
+                wxYield();
+
+            delete data;
+        }
+
+        // @@@ our return value indicates success even if execvp() in the child
+        //     failed!
+        return pid;
     }
 }
 
     }
 }
 
@@ -389,7 +392,7 @@ long wxExecute( const wxString& command, bool sync, wxProcess *process )
         /* loop */ ;
 
     long lRc = wxExecute(argv, sync, process);
         /* loop */ ;
 
     long lRc = wxExecute(argv, sync, process);
-    
+
     delete [] tmp;
 
     return lRc;
     delete [] tmp;
 
     return lRc;
index ba3988e15479b2fabbb1d0fdf3240d4d1c35c6df..fd92f99ba4f94581f47e3aa072a38b316496630b 100644 (file)
@@ -96,7 +96,7 @@ int wxGetOsVersion(int *majorVsn, int *minorVsn)
 {
   if (majorVsn) *majorVsn = GTK_MAJOR_VERSION;
   if (minorVsn) *minorVsn = GTK_MINOR_VERSION;
 {
   if (majorVsn) *majorVsn = GTK_MAJOR_VERSION;
   if (minorVsn) *minorVsn = GTK_MINOR_VERSION;
-  
+
   return wxGTK;
 }
 
   return wxGTK;
 }
 
@@ -123,11 +123,11 @@ char *wxGetUserHome( const wxString &user )
        {
             return ptr;
        }
        {
             return ptr;
        }
-        if ((ptr = getenv("USER")) != NULL || (ptr = getenv("LOGNAME")) != NULL) 
+        if ((ptr = getenv("USER")) != NULL || (ptr = getenv("LOGNAME")) != NULL)
        {
             who = getpwnam(ptr);
         }
        {
             who = getpwnam(ptr);
         }
-       
+
         /* We now make sure the the user exists! */
         if (who == NULL)
        {
         /* We now make sure the the user exists! */
         if (who == NULL)
        {
@@ -299,10 +299,10 @@ long wxExecute( char **argv, bool sync, wxProcess *process )
     wxCHECK_MSG( *argv, 0, "can't exec empty command" );
 
     /* Create pipes */
     wxCHECK_MSG( *argv, 0, "can't exec empty command" );
 
     /* Create pipes */
-    if (pipe(end_proc_detect) == -1) 
+    if (pipe(end_proc_detect) == -1)
     {
     {
-      wxLogSysError( "Pipe creation failed" );
-      return 0;
+        wxLogSysError( "Pipe creation failed" );
+        return 0;
     }
 
     /* fork the process */
     }
 
     /* fork the process */
@@ -311,65 +311,68 @@ long wxExecute( char **argv, bool sync, wxProcess *process )
 #else
     pid_t pid = fork();
 #endif
 #else
     pid_t pid = fork();
 #endif
-    if (pid == -1) 
+    if (pid == -1)
     {
         wxLogSysError( "Fork failed" );
         return 0;
     }
     {
         wxLogSysError( "Fork failed" );
         return 0;
     }
-    else if (pid == 0) 
+    else if (pid == 0)
     {
         // we're in child
         close(end_proc_detect[0]); // close reading side
     {
         // we're in child
         close(end_proc_detect[0]); // close reading side
-       // These three lines close the open file descriptors to
-       // to avoid any input/output which might block the process
-       // or irritate the user. If one wants proper IO for the sub-
-       // process, the "right thing to do" is to start an xterm executing
-       // it.
-       close(STDIN_FILENO);
-       close(STDOUT_FILENO);
-       close(STDERR_FILENO);
+
+        // These three lines close the open file descriptors to
+        // to avoid any input/output which might block the process
+        // or irritate the user. If one wants proper IO for the sub-
+        // process, the "right thing to do" is to start an xterm executing
+        // it.
+        close(STDIN_FILENO);
+        close(STDOUT_FILENO);
+        close(STDERR_FILENO);
+
         // some programs complain about sterr not being open, so
         // redirect them:
         open("/dev/null", O_RDONLY);  // stdin
         // some programs complain about sterr not being open, so
         // redirect them:
         open("/dev/null", O_RDONLY);  // stdin
-       open("/dev/null", O_WRONLY);  // stdout
-       open("/dev/null", O_WRONLY);  // stderr
-        
+        open("/dev/null", O_WRONLY);  // stdout
+        open("/dev/null", O_WRONLY);  // stderr
+
 
 #ifdef _AIX
         execvp ((const char *)*argv, (const char **)argv);
 #else
         execvp (*argv, argv);
 #endif
 
 #ifdef _AIX
         execvp ((const char *)*argv, (const char **)argv);
 #else
         execvp (*argv, argv);
 #endif
+
         // there is no return after successful exec()
         wxLogSysError( "Can't execute '%s'", *argv);
 
         _exit(-1);
     }
         // there is no return after successful exec()
         wxLogSysError( "Can't execute '%s'", *argv);
 
         _exit(-1);
     }
-    else 
+    else
     {
     {
-      // we're in parent
-      close(end_proc_detect[1]); // close writing side
-      data->tag = gdk_input_add(end_proc_detect[0], GDK_INPUT_READ,
-                                GTK_EndProcessDetector, (gpointer)data);
-      data->pid = pid;
-      if (!sync) 
-      {
-        data->process = process;
-      }
-      else 
-      {
-        data->process = (wxProcess *) NULL;
-        data->pid = -(data->pid);
-
-        while (data->pid != 0)
-          wxYield();
-
-        delete data;
-      }
-
-      // @@@ our return value indicates success even if execvp() in the child
-      //     failed!
-      return pid;
+        // we're in parent
+        close(end_proc_detect[1]); // close writing side
+        data->tag = gdk_input_add(end_proc_detect[0], GDK_INPUT_READ,
+                GTK_EndProcessDetector, (gpointer)data);
+        data->pid = pid;
+        if (!sync)
+        {
+            data->process = process;
+        }
+        else
+        {
+            data->process = (wxProcess *) NULL;
+            data->pid = -(data->pid);
+
+            while (data->pid != 0)
+                wxYield();
+
+            delete data;
+        }
+
+        // @@@ our return value indicates success even if execvp() in the child
+        //     failed!
+        return pid;
     }
 }
 
     }
 }
 
@@ -389,7 +392,7 @@ long wxExecute( const wxString& command, bool sync, wxProcess *process )
         /* loop */ ;
 
     long lRc = wxExecute(argv, sync, process);
         /* loop */ ;
 
     long lRc = wxExecute(argv, sync, process);
-    
+
     delete [] tmp;
 
     return lRc;
     delete [] tmp;
 
     return lRc;