]> git.saurik.com Git - wxWidgets.git/commitdiff
added wxEXEC_BLOCK flag (patch 1620430)
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 8 Apr 2007 00:18:09 +0000 (00:18 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 8 Apr 2007 00:18:09 +0000 (00:18 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45325 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
docs/latex/wx/function.tex
include/wx/utils.h
src/unix/utilsunx.cpp

index b9068df632ff1921cb1b096fd419009ae354693e..11341667f00ebbb2773e3913ac55fe070a5ff6a2 100644 (file)
@@ -79,6 +79,7 @@ All:
 - Added wxMutex::LockTimeout() (Aleksandr Napylov)
 - Added wxMemoryInputStream(wxInputStream&) ctor (Stas Sergeev)
 - Implemented wxMemoryInputStream::CanRead()
 - Added wxMutex::LockTimeout() (Aleksandr Napylov)
 - Added wxMemoryInputStream(wxInputStream&) ctor (Stas Sergeev)
 - Implemented wxMemoryInputStream::CanRead()
+- Added wxEXEC_BLOCK flag (Hank Schultz)
 
 All (GUI):
 
 
 All (GUI):
 
index c6db80094deb52b4875ae45aaa84de631396d369..fe1e582e8a036be629e0b53fff317c212220f50d 100644 (file)
@@ -647,6 +647,13 @@ needed). Calling \helpref{wxKill}{wxkill} passing wxKILL\_CHILDREN will
 kill this process as well as all of its children (except those which have
 started their own session).
 
 kill this process as well as all of its children (except those which have
 started their own session).
 
+The {\tt wxEXEC\_NOEVENTS} flag prevents processing of any events from taking
+place while the child process is running. It should be only used for very
+short-lived processes as otherwise the application windows risk becoming
+unresponsive from the users point of view. As this flag only makes sense with
+{\tt wxEXEC\_SYNC}, {\tt wxEXEC\_BLOCK} equal to the sum of both of these flags
+is provided as a convenience.
+
 Finally, you may use the third overloaded version of this function to execute
 a process (always synchronously, the contents of \arg{flags} is or'd with
 \texttt{wxEXEC\_SYNC}) and capture its output in the array \arg{output}. The
 Finally, you may use the third overloaded version of this function to execute
 a process (always synchronously, the contents of \arg{flags} is or'd with
 \texttt{wxEXEC\_SYNC}) and capture its output in the array \arg{output}. The
index aec1d1ee500655d41862fd6ddfd8a1b0f07f7ed9..4e4c71a58dea5145c1c32cc7ee4fa8ba1f425207 100644 (file)
@@ -320,7 +320,15 @@ enum
     // by default synchronous execution disables all program windows to avoid
     // that the user interacts with the program while the child process is
     // running, you can use this flag to prevent this from happening
     // by default synchronous execution disables all program windows to avoid
     // that the user interacts with the program while the child process is
     // running, you can use this flag to prevent this from happening
-    wxEXEC_NODISABLE = 8
+    wxEXEC_NODISABLE = 8,
+
+    // by default, the event loop is run while waiting for synchronous execution
+    // to complete and this flag can be used to simply block the main process
+    // until the child process finishes
+    wxEXEC_NOEVENTS = 16,
+
+    // convenient synonym for flags given system()-like behaviour
+    wxEXEC_BLOCK = wxEXEC_SYNC | wxEXEC_NOEVENTS
 };
 
 // Execute another program.
 };
 
 // Execute another program.
index ff387a51247714dd28367b3516a7827017c7af23..cdaa1599230b334de3dfe6d17307ac570325b82d 100644 (file)
@@ -38,6 +38,7 @@
 #include "wx/unix/private.h"
 
 #include <pwd.h>
 #include "wx/unix/private.h"
 
 #include <pwd.h>
+#include <sys/wait.h>       // waitpid()
 
 #ifdef HAVE_SYS_SELECT_H
 #   include <sys/select.h>
 
 #ifdef HAVE_SYS_SELECT_H
 #   include <sys/select.h>
@@ -1237,55 +1238,93 @@ int wxGUIAppTraits::WaitForChild(wxExecuteData& execData)
     }
 
 
     }
 
 
+    if ( !(flags & wxEXEC_NOEVENTS) )
+    {
 #if defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__))
 #if defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__))
-    endProcData->tag = wxAddProcessCallbackForPid(endProcData, execData.pid);
+        endProcData->tag = wxAddProcessCallbackForPid(endProcData, execData.pid);
 #else
 #else
-    endProcData->tag = wxAddProcessCallback
-                (
-                    endProcData,
-                    execData.pipeEndProcDetect.Detach(wxPipe::Read)
-                );
+        endProcData->tag = wxAddProcessCallback
+                           (
+                             endProcData,
+                             execData.pipeEndProcDetect.Detach(wxPipe::Read)
+                           );
 
 
-    execData.pipeEndProcDetect.Close();
+        execData.pipeEndProcDetect.Close();
 #endif // defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__))
 #endif // defined(__DARWIN__) && (defined(__WXMAC__) || defined(__WXCOCOA__))
+    }
 
     if ( flags & wxEXEC_SYNC )
     {
         wxBusyCursor bc;
 
     if ( flags & wxEXEC_SYNC )
     {
         wxBusyCursor bc;
-        wxWindowDisabler *wd = flags & wxEXEC_NODISABLE ? NULL
-                                                        : new wxWindowDisabler;
+        int exitcode = 0;
+
+        wxWindowDisabler *wd = flags & (wxEXEC_NODISABLE | wxEXEC_NOEVENTS)
+                                    ? NULL
+                                    : new wxWindowDisabler;
 
 
-        // endProcData->pid will be set to 0 from GTK_EndProcessDetector when the
-        // process terminates
-        while ( endProcData->pid != 0 )
+        if ( flags & wxEXEC_NOEVENTS )
         {
         {
-            bool idle = true;
+            // just block waiting for the child to exit
+            int status = 0;
 
 
-#if HAS_PIPE_INPUT_STREAM
-            if ( execData.bufOut )
+            int result = waitpid(execData.pid, &status, 0);
+
+            if ( result == -1 )
             {
             {
-                execData.bufOut->Update();
-                idle = false;
+                wxLogLastError(_T("waitpid"));
+                exitcode = -1;
             }
             }
-
-            if ( execData.bufErr )
+            else
             {
             {
-                execData.bufErr->Update();
-                idle = false;
+                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
 
 #endif // HAS_PIPE_INPUT_STREAM
 
-            // don't consume 100% of the CPU while we're sitting in this
-            // loop
-            if ( idle )
-                wxMilliSleep(1);
+                // 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();
-        }
+                // give GTK+ a chance to call GTK_EndProcessDetector here and
+                // also repaint the GUI
+                wxYield();
+            }
 
 
-        int exitcode = endProcData->exitcode;
+            exitcode = endProcData->exitcode;
+        }
 
         delete wd;
         delete endProcData;
 
         delete wd;
         delete endProcData;