]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/utilsunx.cpp
Implement support for button mnemonics in wxOSX/Cocoa.
[wxWidgets.git] / src / unix / utilsunx.cpp
index 282f4392585735b35e034374bb16ffcba280b435..a09fb424df8fca1bcc043df3dba4d49dff65dad3 100644 (file)
 
 #endif // HAS_PIPE_STREAMS
 
-#if defined(__MWERKS__) && defined(__MACH__)
-    #ifndef WXWIN_OS_DESCRIPTION
-        #define WXWIN_OS_DESCRIPTION "MacOS X"
-    #endif
-    #ifndef HAVE_NANOSLEEP
-        #define HAVE_NANOSLEEP
-    #endif
-    #ifndef HAVE_UNAME
-        #define HAVE_UNAME
-    #endif
-
-    // our configure test believes we can use sigaction() if the function is
-    // available but Metrowekrs with MSL run-time does have the function but
-    // doesn't have sigaction struct so finally we can't use it...
-    #ifdef __MSL__
-        #undef wxUSE_ON_FATAL_EXCEPTION
-        #define wxUSE_ON_FATAL_EXCEPTION 0
-    #endif
-#endif
-
 // not only the statfs syscall is called differently depending on platform, but
 // one of its incarnations, statvfs(), takes different arguments under
 // different platforms and even different versions of the same system (Solaris
@@ -337,6 +317,45 @@ bool wxPipeInputStream::CanRead() const
     }
 }
 
+size_t wxPipeOutputStream::OnSysWrite(const void *buffer, size_t size)
+{
+    // We need to suppress error logging here, because on writing to a pipe
+    // which is full, wxFile::Write reports a system error. However, this is
+    // not an extraordinary situation, and it should not be reported to the
+    // user (but if really needed, the program can recognize it by checking
+    // whether LastRead() == 0.) Other errors will be reported below.
+    size_t ret;
+    {
+        wxLogNull logNo;
+        ret = m_file->Write(buffer, size);
+    }
+
+    switch ( m_file->GetLastError() )
+    {
+       // pipe is full
+#ifdef EAGAIN
+       case EAGAIN:
+#endif
+#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
+       case EWOULDBLOCK:
+#endif
+           // do not treat it as an error
+           m_file->ClearLastError();
+           // fall through
+
+       // no error
+       case 0:
+           break;
+
+       // some real error
+       default:
+           wxLogSysError(_("Can't write to child process's stdin"));
+           m_lasterror = wxSTREAM_WRITE_ERROR;
+    }
+
+    return ret;
+}
+
 #endif // HAS_PIPE_STREAMS
 
 // ----------------------------------------------------------------------------
@@ -559,12 +578,6 @@ long wxExecute(char **argv, int flags, wxProcess *process,
         }
 #endif // !__VMS
 
-        // reading side can be safely closed but we should keep the write one
-        // opened, it will be only closed when the process terminates resulting
-        // in a read notification to the parent
-        execData.pipeEndProcDetect.Detach(wxPipe::Write);
-        execData.pipeEndProcDetect.Close();
-
         // redirect stdin, stdout and stderr
         if ( pipeIn.IsOk() )
         {
@@ -580,6 +593,39 @@ long wxExecute(char **argv, int flags, wxProcess *process,
             pipeErr.Close();
         }
 
+        // Close all (presumably accidentally) inherited file descriptors to
+        // avoid descriptor leaks. This means that we don't allow inheriting
+        // them purposefully but this seems like a lesser evil in wx code.
+        // Ideally we'd provide some flag to indicate that none (or some?) of
+        // the descriptors do not need to be closed but for now this is better
+        // than never closing them at all as wx code never used FD_CLOEXEC.
+
+        // Note that while the reading side of the end process detection pipe
+        // can be safely closed, we should keep the write one opened, it will
+        // be only closed when the process terminates resulting in a read
+        // notification to the parent
+        const int fdEndProc = execData.pipeEndProcDetect.Detach(wxPipe::Write);
+        execData.pipeEndProcDetect.Close();
+
+        // TODO: Iterating up to FD_SETSIZE is both inefficient (because it may
+        //       be quite big) and incorrect (because in principle we could
+        //       have more opened descriptions than this number). Unfortunately
+        //       there is no good portable solution for closing all descriptors
+        //       above a certain threshold but non-portable solutions exist for
+        //       most platforms, see [http://stackoverflow.com/questions/899038/
+        //          getting-the-highest-allocated-file-descriptor]
+        for ( int fd = 0; fd < (int)FD_SETSIZE; ++fd )
+        {
+            if ( fd != STDIN_FILENO  &&
+                 fd != STDOUT_FILENO &&
+                 fd != STDERR_FILENO &&
+                 fd != fdEndProc )
+            {
+                close(fd);
+            }
+        }
+
+
         // Process additional options if we have any
         if ( env )
         {
@@ -662,10 +708,13 @@ long wxExecute(char **argv, int flags, wxProcess *process,
                 // it might not be the best idea.
                 wxLogSysError(_("Failed to set up non-blocking pipe, "
                                 "the program might hang."));
+#if wxUSE_LOG
+                wxLog::FlushActive();
+#endif
             }
 
             wxOutputStream *inStream =
-                new wxFileOutputStream(pipeIn.Detach(wxPipe::Write));
+                new wxPipeOutputStream(pipeIn.Detach(wxPipe::Write));
 
             const int fdOut = pipeOut.Detach(wxPipe::Read);
             wxPipeInputStream *outStream = new wxPipeInputStream(fdOut);
@@ -943,7 +992,7 @@ wxLinuxDistributionInfo wxGetLinuxDistributionInfo()
 #endif
 
 // these functions are in src/osx/utilsexc_base.cpp for wxMac
-#ifndef __WXMAC__
+#ifndef __DARWIN__
 
 wxOperatingSystemId wxGetOsVersion(int *verMaj, int *verMin)
 {
@@ -979,7 +1028,7 @@ wxString wxGetOsDescription()
     return wxGetCommandOutput(wxT("uname -s -r -m"));
 }
 
-#endif // !__WXMAC__
+#endif // !__DARWIN__
 
 unsigned long wxGetProcessId()
 {