X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7e84f02dfda7d5e3cf2cef1aa85169c55e8d4461..41895a05eae22da85e8c659f9492d2312a63af13:/src/gtk/utilsgtk.cpp diff --git a/src/gtk/utilsgtk.cpp b/src/gtk/utilsgtk.cpp index fd92f99ba4..a55812182a 100644 --- a/src/gtk/utilsgtk.cpp +++ b/src/gtk/utilsgtk.cpp @@ -43,14 +43,26 @@ #include #endif -#ifdef __SOLARIS__ -// somehow missing from sys/wait.h but in the system's docs -extern "C" -{ - pid_t wait4(pid_t pid, int *statusp, int options, struct rusage - *rusage); -} -#endif +// many versions of Unices have this function, but it is not defined in system +// headers - please add your system here if it is the case for your OS. +// SunOS (and Solaris) and DG-UX are like this. +#if defined(__SOLARIS__) || defined(__osf__) + extern "C" + { + pid_t wait4(pid_t pid, int *statusp, int options, + struct rusage *rusage); + } + + #define wxWait4(pid, stat, flags, rusage) wait4(pid, stat, flags, rusage) +#elif defined(__sgi) || defined(__HPUX__) + // no wait4() at all on these systems + // TODO verify whether wait3() really works in this situation + #define wxWait4(pid, stat, flags, rusage) wait3(stat, flags, rusage) +#else + // other Unices: assume have wait4(), although it's not standard (but + // Linux and FreeBSD do have it) + #define wxWait4(pid, stat, flags, rusage) wait4(pid, stat, flags, rusage) +#endif // wait4() //------------------------------------------------------------------------ // misc. @@ -252,10 +264,14 @@ bool wxDirExists( const wxString& dir ) // subprocess routines //------------------------------------------------------------------------ +// if pid > 0, the execution is async and the data is freed in +// GTK_EndProcessDetector, if pid < 0, the execution is synchronous and the +// caller (wxExecute) frees the data struct wxEndProcessData { gint pid, tag; wxProcess *process; + int exitcode; }; static void GTK_EndProcessDetector(gpointer data, gint source, @@ -266,18 +282,8 @@ static void GTK_EndProcessDetector(gpointer data, gint source, pid = (proc_data->pid > 0) ? proc_data->pid : -(proc_data->pid); - /* wait4 is not part of any standard, use at own risk - * not sure what wait4 does, but wait3 seems to be closest, whats a digit ;-) - * --- offer@sgi.com */ - // VZ: wait4() will be woken up by a signal, not wait3 - so it's quite - // different (also, wait3() waits for any child, wait4() only for this - // one) - int status = -1; -#if !defined(__sgi) - wait4(proc_data->pid, &status, 0, (rusage *) NULL); -#else - wait3(&status, 0, (rusage *) NULL); -#endif + int status = 0; + wxWait4(pid, &status, 0, (rusage *) NULL); close(source); gdk_input_remove(proc_data->tag); @@ -286,9 +292,16 @@ static void GTK_EndProcessDetector(gpointer data, gint source, proc_data->process->OnTerminate(proc_data->pid, status); if (proc_data->pid > 0) + { delete proc_data; + } else + { + // wxExecute() will know about it + proc_data->exitcode = status; + proc_data->pid = 0; + } } long wxExecute( char **argv, bool sync, wxProcess *process ) @@ -301,7 +314,7 @@ long wxExecute( char **argv, bool sync, wxProcess *process ) /* Create pipes */ if (pipe(end_proc_detect) == -1) { - wxLogSysError( "Pipe creation failed" ); + wxLogSysError( _("Pipe creation failed") ); return 0; } @@ -313,7 +326,7 @@ long wxExecute( char **argv, bool sync, wxProcess *process ) #endif if (pid == -1) { - wxLogSysError( "Fork failed" ); + wxLogSysError( _("Fork failed") ); return 0; } else if (pid == 0) @@ -321,21 +334,23 @@ long wxExecute( char **argv, bool sync, wxProcess *process ) // 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. + // 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 subprocess, the "right thing to do is + // to start an xterm executing it. close(STDIN_FILENO); close(STDOUT_FILENO); + + // leave stderr opened, it won't do any hurm +#if 0 close(STDERR_FILENO); - // some programs complain about sterr not being open, so - // redirect them: + // some programs complain about stderr not being open, so redirect + // them: open("/dev/null", O_RDONLY); // stdin open("/dev/null", O_WRONLY); // stdout open("/dev/null", O_WRONLY); // stderr - +#endif #ifdef _AIX execvp ((const char *)*argv, (const char **)argv); @@ -344,7 +359,7 @@ long wxExecute( char **argv, bool sync, wxProcess *process ) #endif // there is no return after successful exec() - wxLogSysError( "Can't execute '%s'", *argv); + fprintf(stderr, _("Can't execute '%s'\n"), *argv); _exit(-1); } @@ -353,26 +368,35 @@ long wxExecute( char **argv, bool sync, wxProcess *process ) // 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 + GTK_EndProcessDetector, (gpointer)data); + if ( sync ) { - data->process = (wxProcess *) NULL; - data->pid = -(data->pid); + wxASSERT_MSG( !process, "wxProcess param ignored for sync exec" ); + data->process = NULL; + // sync execution: indicate it by negating the pid + data->pid = -pid; + + // it will be set to 0 from GTK_EndProcessDetector while (data->pid != 0) wxYield(); + int exitcode = data->exitcode; + delete data; + + return exitcode; } + else + { + // async execution, nothing special to do - caller will be + // notified about the process terminationif process != NULL, data + // will be deleted in GTK_EndProcessDetector + data->process = process; + data->pid = pid; - // @@@ our return value indicates success even if execvp() in the child - // failed! - return pid; + return pid; + } } }