ENH: Changes based on patch from Ryan C. Gordon to enable process execution on BeOS. There seems to be no way to implement it without polling (or threads).
This commit is contained in:
parent
d045ae45f2
commit
de8ffcaef4
|
@ -75,6 +75,36 @@ typedef ssize_t kwsysProcess_ssize_t;
|
|||
typedef int kwsysProcess_ssize_t;
|
||||
#endif
|
||||
|
||||
#if defined(__BEOS__) && !defined(__ZETA__)
|
||||
/* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */
|
||||
# include <be/kernel/OS.h>
|
||||
static inline void kwsysProcess_usleep(unsigned int msec)
|
||||
{
|
||||
snooze(msec);
|
||||
}
|
||||
#else
|
||||
# define kwsysProcess_usleep usleep
|
||||
#endif
|
||||
|
||||
/*
|
||||
* BeOS's select() works like WinSock: it's for networking only, and
|
||||
* doesn't work with Unix file handles...socket and file handles are
|
||||
* different namespaces (the same descriptor means different things in
|
||||
* each context!)
|
||||
*
|
||||
* So on Unix-like systems where select() is flakey, we'll set the
|
||||
* pipes' file handles to be non-blocking and just poll them directly
|
||||
* without select().
|
||||
*/
|
||||
#if !defined(__BEOS__)
|
||||
# define KWSYSPE_USE_SELECT 1
|
||||
#endif
|
||||
|
||||
/* BeOS does not have siginfo on its signal handlers. */
|
||||
#if !defined(__BEOS__)
|
||||
# define KWSYSPE_USE_SIGINFO 1
|
||||
#endif
|
||||
|
||||
/* The number of pipes for the child's output. The standard stdout
|
||||
and stderr pipes are the first two. One more pipe is used to
|
||||
detect when the child process has terminated. The third pipe is
|
||||
|
@ -111,6 +141,7 @@ typedef struct kwsysProcessCreateInformation_s
|
|||
static int kwsysProcessInitialize(kwsysProcess* cp);
|
||||
static void kwsysProcessCleanup(kwsysProcess* cp, int error);
|
||||
static void kwsysProcessCleanupDescriptor(int* pfd);
|
||||
static int kwsysProcessSetNonBlocking(int fd);
|
||||
static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
|
||||
kwsysProcessCreateInformation* si, int* readEnd);
|
||||
static void kwsysProcessDestroy(kwsysProcess* cp);
|
||||
|
@ -135,8 +166,12 @@ static pid_t kwsysProcessFork(kwsysProcess* cp,
|
|||
static void kwsysProcessKill(pid_t process_id);
|
||||
static int kwsysProcessesAdd(kwsysProcess* cp);
|
||||
static void kwsysProcessesRemove(kwsysProcess* cp);
|
||||
#if KWSYSPE_USE_SIGINFO
|
||||
static void kwsysProcessesSignalHandler(int signum, siginfo_t* info,
|
||||
void* ucontext);
|
||||
#else
|
||||
static void kwsysProcessesSignalHandler(int signum);
|
||||
#endif
|
||||
static char** kwsysProcessParseVerbatimCommand(const char* command);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
@ -190,8 +225,10 @@ struct kwsysProcess_s
|
|||
/* The number of pipes left open during execution. */
|
||||
int PipesLeft;
|
||||
|
||||
#if KWSYSPE_USE_SELECT
|
||||
/* File descriptor set for call to select. */
|
||||
fd_set PipeSet;
|
||||
#endif
|
||||
|
||||
/* The number of children still executing. */
|
||||
int CommandsLeft;
|
||||
|
@ -731,6 +768,15 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
|||
kwsysProcessCleanupDescriptor(&si.StdErr);
|
||||
return;
|
||||
}
|
||||
|
||||
#if !KWSYSPE_USE_SELECT
|
||||
if(!kwsysProcessSetNonBlocking(p[0]))
|
||||
{
|
||||
kwsysProcessCleanup(cp, 1);
|
||||
kwsysProcessCleanupDescriptor(&si.StdErr);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Replace the stderr pipe with a file if requested. In this case
|
||||
|
@ -775,9 +821,24 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
|||
/* Create the pipeline of processes. */
|
||||
{
|
||||
int readEnd = -1;
|
||||
int failed = 0;
|
||||
for(i=0; i < cp->NumberOfCommands; ++i)
|
||||
{
|
||||
if(!kwsysProcessCreate(cp, i, &si, &readEnd))
|
||||
{
|
||||
failed = 1;
|
||||
}
|
||||
|
||||
#if !KWSYSPE_USE_SELECT
|
||||
/* Set the output pipe of the last process to be non-blocking so
|
||||
we can poll it. */
|
||||
if(i == cp->NumberOfCommands-1 && !kwsysProcessSetNonBlocking(readEnd))
|
||||
{
|
||||
failed = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(failed)
|
||||
{
|
||||
kwsysProcessCleanup(cp, 1);
|
||||
|
||||
|
@ -846,8 +907,11 @@ kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp)
|
|||
{
|
||||
if(cp->PipeReadEnds[i] >= 0)
|
||||
{
|
||||
#if KWSYSPE_USE_SELECT
|
||||
/* If the pipe was reported by the last call to select, we must
|
||||
read from it. Ignore the data. */
|
||||
read from it. This is needed to satisfy the suggestions from
|
||||
"man select_tut" and is not needed for the polling
|
||||
implementation. Ignore the data. */
|
||||
if(FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet))
|
||||
{
|
||||
/* We are handling this pipe now. Remove it from the set. */
|
||||
|
@ -858,6 +922,7 @@ kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp)
|
|||
while((read(cp->PipeReadEnds[i], cp->PipeBuffer,
|
||||
KWSYSPE_PIPE_BUFFER_SIZE) < 0) && (errno == EINTR));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* We are done reading from this pipe. */
|
||||
kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
|
||||
|
@ -872,20 +937,31 @@ kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp)
|
|||
cp->State = kwsysProcess_State_Disowned;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
typedef struct kwsysProcessWaitData_s
|
||||
{
|
||||
int Expired;
|
||||
int PipeId;
|
||||
int User;
|
||||
double* UserTimeout;
|
||||
kwsysProcessTime TimeoutTime;
|
||||
} kwsysProcessWaitData;
|
||||
static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
|
||||
kwsysProcessWaitData* wd);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
|
||||
double* userTimeout)
|
||||
{
|
||||
int i;
|
||||
int max = -1;
|
||||
kwsysProcessTimeNative* timeout = 0;
|
||||
kwsysProcessTimeNative timeoutLength;
|
||||
kwsysProcessTime timeoutTime;
|
||||
kwsysProcessTime userStartTime = {0, 0};
|
||||
int user = 0;
|
||||
int expired = 0;
|
||||
int pipeId = kwsysProcess_Pipe_None;
|
||||
int numReady = 0;
|
||||
kwsysProcessWaitData wd =
|
||||
{
|
||||
0,
|
||||
kwsysProcess_Pipe_None,
|
||||
0,
|
||||
userTimeout,
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
/* Make sure we are executing a process. */
|
||||
if(!cp || cp->State != kwsysProcess_State_Executing || cp->Killed ||
|
||||
|
@ -902,12 +978,70 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
|
|||
|
||||
/* Calculate the time at which a timeout will expire, and whether it
|
||||
is the user or process timeout. */
|
||||
user = kwsysProcessGetTimeoutTime(cp, userTimeout, &timeoutTime);
|
||||
wd.User = kwsysProcessGetTimeoutTime(cp, userTimeout,
|
||||
&wd.TimeoutTime);
|
||||
|
||||
/* Data can only be available when pipes are open. If the process
|
||||
is not running, cp->PipesLeft will be 0. */
|
||||
while(cp->PipesLeft > 0)
|
||||
while(cp->PipesLeft > 0 &&
|
||||
!kwsysProcessWaitForPipe(cp, data, length, &wd)) {}
|
||||
|
||||
/* Update the user timeout. */
|
||||
if(userTimeout)
|
||||
{
|
||||
kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent();
|
||||
kwsysProcessTime difference = kwsysProcessTimeSubtract(userEndTime,
|
||||
userStartTime);
|
||||
double d = kwsysProcessTimeToDouble(difference);
|
||||
*userTimeout -= d;
|
||||
if(*userTimeout < 0)
|
||||
{
|
||||
*userTimeout = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check what happened. */
|
||||
if(wd.PipeId)
|
||||
{
|
||||
/* Data are ready on a pipe. */
|
||||
return wd.PipeId;
|
||||
}
|
||||
else if(wd.Expired)
|
||||
{
|
||||
/* A timeout has expired. */
|
||||
if(wd.User)
|
||||
{
|
||||
/* The user timeout has expired. It has no time left. */
|
||||
return kwsysProcess_Pipe_Timeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The process timeout has expired. Kill the children now. */
|
||||
kwsysProcess_Kill(cp);
|
||||
cp->Killed = 0;
|
||||
cp->TimeoutExpired = 1;
|
||||
return kwsysProcess_Pipe_None;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No pipes are left open. */
|
||||
return kwsysProcess_Pipe_None;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int kwsysProcessWaitForPipe(kwsysProcess* cp, char** data, int* length,
|
||||
kwsysProcessWaitData* wd)
|
||||
{
|
||||
int i;
|
||||
kwsysProcessTimeNative timeoutLength;
|
||||
|
||||
#if KWSYSPE_USE_SELECT
|
||||
int numReady = 0;
|
||||
int max = -1;
|
||||
kwsysProcessTimeNative* timeout = 0;
|
||||
|
||||
/* Check for any open pipes with data reported ready by the last
|
||||
call to select. According to "man select_tut" we must deal
|
||||
with all descriptors reported by a call to select before
|
||||
|
@ -942,11 +1076,11 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
|
|||
switch(i)
|
||||
{
|
||||
case KWSYSPE_PIPE_STDOUT:
|
||||
pipeId = kwsysProcess_Pipe_STDOUT; break;
|
||||
wd->PipeId = kwsysProcess_Pipe_STDOUT; break;
|
||||
case KWSYSPE_PIPE_STDERR:
|
||||
pipeId = kwsysProcess_Pipe_STDERR; break;
|
||||
wd->PipeId = kwsysProcess_Pipe_STDERR; break;
|
||||
};
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -959,9 +1093,9 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
|
|||
}
|
||||
|
||||
/* If we have data, break early. */
|
||||
if(pipeId)
|
||||
if(wd->PipeId)
|
||||
{
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Make sure the set is empty (it should always be empty here
|
||||
|
@ -969,7 +1103,7 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
|
|||
FD_ZERO(&cp->PipeSet);
|
||||
|
||||
/* Setup a timeout if required. */
|
||||
if(timeoutTime.tv_sec < 0)
|
||||
if(wd->TimeoutTime.tv_sec < 0)
|
||||
{
|
||||
timeout = 0;
|
||||
}
|
||||
|
@ -977,11 +1111,13 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
|
|||
{
|
||||
timeout = &timeoutLength;
|
||||
}
|
||||
if(kwsysProcessGetTimeoutLeft(&timeoutTime, user?userTimeout:0, &timeoutLength))
|
||||
if(kwsysProcessGetTimeoutLeft(&wd->TimeoutTime,
|
||||
wd->User?wd->UserTimeout:0,
|
||||
&timeoutLength))
|
||||
{
|
||||
/* Timeout has already expired. */
|
||||
expired = 1;
|
||||
break;
|
||||
wd->Expired = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Add the pipe reading ends that are still open. */
|
||||
|
@ -1002,7 +1138,7 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
|
|||
if(max < 0)
|
||||
{
|
||||
/* All pipes have closed. Child has terminated. */
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Run select to block until data are available. Repeat call
|
||||
|
@ -1014,8 +1150,8 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
|
|||
if(numReady == 0)
|
||||
{
|
||||
/* Select's timeout expired. */
|
||||
expired = 1;
|
||||
break;
|
||||
wd->Expired = 1;
|
||||
return 1;
|
||||
}
|
||||
else if(numReady < 0)
|
||||
{
|
||||
|
@ -1028,50 +1164,94 @@ int kwsysProcess_WaitForData(kwsysProcess* cp, char** data, int* length,
|
|||
cp->Killed = 0;
|
||||
cp->SelectError = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the user timeout. */
|
||||
if(userTimeout)
|
||||
return 0;
|
||||
#else
|
||||
/* Poll pipes for data since we do not have select. */
|
||||
for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
|
||||
{
|
||||
kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent();
|
||||
kwsysProcessTime difference = kwsysProcessTimeSubtract(userEndTime,
|
||||
userStartTime);
|
||||
double d = kwsysProcessTimeToDouble(difference);
|
||||
*userTimeout -= d;
|
||||
if(*userTimeout < 0)
|
||||
if(cp->PipeReadEnds[i] >= 0)
|
||||
{
|
||||
*userTimeout = 0;
|
||||
const int fd = cp->PipeReadEnds[i];
|
||||
int n = read(fd, cp->PipeBuffer, KWSYSPE_PIPE_BUFFER_SIZE);
|
||||
if(n > 0)
|
||||
{
|
||||
/* We have data on this pipe. */
|
||||
if(i == KWSYSPE_PIPE_SIGNAL)
|
||||
{
|
||||
/* A child process has terminated. */
|
||||
kwsysProcessDestroy(cp);
|
||||
}
|
||||
else if(data && length)
|
||||
{
|
||||
/* Report this data. */
|
||||
*data = cp->PipeBuffer;
|
||||
*length = n;
|
||||
switch(i)
|
||||
{
|
||||
case KWSYSPE_PIPE_STDOUT:
|
||||
wd->PipeId = kwsysProcess_Pipe_STDOUT; break;
|
||||
case KWSYSPE_PIPE_STDERR:
|
||||
wd->PipeId = kwsysProcess_Pipe_STDERR; break;
|
||||
};
|
||||
}
|
||||
|
||||
/* Check what happened. */
|
||||
if(pipeId)
|
||||
{
|
||||
/* Data are ready on a pipe. */
|
||||
return pipeId;
|
||||
return 1;
|
||||
}
|
||||
else if(expired)
|
||||
else if (n == 0) /* EOF */
|
||||
{
|
||||
/* A timeout has expired. */
|
||||
if(user)
|
||||
{
|
||||
/* The user timeout has expired. It has no time left. */
|
||||
return kwsysProcess_Pipe_Timeout;
|
||||
/* We are done reading from this pipe. */
|
||||
kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
|
||||
--cp->PipesLeft;
|
||||
}
|
||||
else
|
||||
else if (n < 0) /* error */
|
||||
{
|
||||
/* The process timeout has expired. Kill the children now. */
|
||||
if((errno != EINTR) && (errno != EAGAIN))
|
||||
{
|
||||
strncpy(cp->ErrorMessage,strerror(errno),
|
||||
KWSYSPE_PIPE_BUFFER_SIZE);
|
||||
/* Kill the children now. */
|
||||
kwsysProcess_Kill(cp);
|
||||
cp->Killed = 0;
|
||||
cp->TimeoutExpired = 1;
|
||||
return kwsysProcess_Pipe_None;
|
||||
cp->SelectError = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have data, break early. */
|
||||
if(wd->PipeId)
|
||||
{
|
||||
/* No pipes are left open. */
|
||||
return kwsysProcess_Pipe_None;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(kwsysProcessGetTimeoutLeft(&wd->TimeoutTime, wd->User?wd->UserTimeout:0,
|
||||
&timeoutLength))
|
||||
{
|
||||
/* Timeout has already expired. */
|
||||
wd->Expired = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if((timeoutLength.tv_sec == 0) && (timeoutLength.tv_usec == 0))
|
||||
{
|
||||
/* Timeout has already expired. */
|
||||
wd->Expired = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Sleep a little, try again. */
|
||||
{
|
||||
unsigned int msec = ((timeoutLength.tv_sec * 1000) +
|
||||
(timeoutLength.tv_usec / 1000));
|
||||
if (msec > 100000)
|
||||
{
|
||||
msec = 100000; /* do not sleep more than 100 milliseconds at a time */
|
||||
}
|
||||
kwsysProcess_usleep(msec);
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
@ -1215,7 +1395,9 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
|
|||
cp->TimeoutExpired = 0;
|
||||
cp->PipesLeft = 0;
|
||||
cp->CommandsLeft = 0;
|
||||
#if KWSYSPE_USE_SELECT
|
||||
FD_ZERO(&cp->PipeSet);
|
||||
#endif
|
||||
cp->State = kwsysProcess_State_Starting;
|
||||
cp->Killed = 0;
|
||||
cp->ExitException = kwsysProcess_Exception_None;
|
||||
|
@ -1351,6 +1533,17 @@ static void kwsysProcessCleanupDescriptor(int* pfd)
|
|||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int kwsysProcessSetNonBlocking(int fd)
|
||||
{
|
||||
int flags = fcntl(fd, F_GETFL);
|
||||
if(flags >= 0)
|
||||
{
|
||||
flags = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
}
|
||||
return flags >= 0;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
|
||||
kwsysProcessCreateInformation* si, int* readEnd)
|
||||
|
@ -2260,10 +2453,8 @@ static int kwsysProcessesAdd(kwsysProcess* cp)
|
|||
|
||||
/* Switch the pipe to non-blocking mode so that reading a byte can
|
||||
be an atomic test-and-set. */
|
||||
if((oldfl[0] = fcntl(p[0], F_GETFL) < 0) ||
|
||||
(oldfl[1] = fcntl(p[1], F_GETFL) < 0) ||
|
||||
(fcntl(p[0], F_SETFL, oldfl[0] | O_NONBLOCK) < 0) ||
|
||||
(fcntl(p[1], F_SETFL, oldfl[1] | O_NONBLOCK) < 0))
|
||||
if(!kwsysProcessSetNonBlocking(p[0]) ||
|
||||
!kwsysProcessSetNonBlocking(p[1]))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -2327,10 +2518,15 @@ static int kwsysProcessesAdd(kwsysProcess* cp)
|
|||
interrupted. */
|
||||
struct sigaction newSigChldAction;
|
||||
memset(&newSigChldAction, 0, sizeof(struct sigaction));
|
||||
#if KWSYSPE_USE_SIGINFO
|
||||
newSigChldAction.sa_sigaction = kwsysProcessesSignalHandler;
|
||||
newSigChldAction.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
|
||||
# ifdef SA_RESTART
|
||||
newSigChldAction.sa_flags |= SA_RESTART;
|
||||
# endif
|
||||
#else
|
||||
newSigChldAction.sa_handler = kwsysProcessesSignalHandler;
|
||||
newSigChldAction.sa_flags = SA_NOCLDSTOP;
|
||||
#endif
|
||||
while((sigaction(SIGCHLD, &newSigChldAction,
|
||||
&kwsysProcessesOldSigChldAction) < 0) &&
|
||||
|
@ -2391,14 +2587,21 @@ static void kwsysProcessesRemove(kwsysProcess* cp)
|
|||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static void kwsysProcessesSignalHandler(int signum, siginfo_t* info,
|
||||
void* ucontext)
|
||||
static void kwsysProcessesSignalHandler(int signum
|
||||
#if KWSYSPE_USE_SIGINFO
|
||||
, siginfo_t* info, void* ucontext
|
||||
#endif
|
||||
)
|
||||
{
|
||||
/* Signal all process objects that a child has terminated. */
|
||||
int i;
|
||||
(void)signum;
|
||||
#if KWSYSPE_USE_SIGINFO
|
||||
(void)info;
|
||||
(void)ucontext;
|
||||
#endif
|
||||
|
||||
/* Signal all process objects that a child has terminated. */
|
||||
{
|
||||
int i;
|
||||
for(i=0; i < kwsysProcesses.Count; ++i)
|
||||
{
|
||||
/* Set the pipe in a signalled state. */
|
||||
|
@ -2409,6 +2612,21 @@ static void kwsysProcessesSignalHandler(int signum, siginfo_t* info,
|
|||
}
|
||||
}
|
||||
|
||||
#if !KWSYSPE_USE_SIGINFO
|
||||
/* Re-Install our handler for SIGCHLD. Repeat call until it is not
|
||||
interrupted. */
|
||||
{
|
||||
struct sigaction newSigChldAction;
|
||||
memset(&newSigChldAction, 0, sizeof(struct sigaction));
|
||||
newSigChldAction.sa_handler = kwsysProcessesSignalHandler;
|
||||
newSigChldAction.sa_flags = SA_NOCLDSTOP;
|
||||
while((sigaction(SIGCHLD, &newSigChldAction,
|
||||
&kwsysProcessesOldSigChldAction) < 0) &&
|
||||
(errno == EINTR));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int kwsysProcessAppendByte(char* local,
|
||||
char** begin, char** end,
|
||||
|
@ -2661,3 +2879,4 @@ static char** kwsysProcessParseVerbatimCommand(const char* command)
|
|||
/* Return the final command buffer. */
|
||||
return newCommand;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,17 @@
|
|||
# pragma warn -8060 /* possibly incorrect assignment */
|
||||
#endif
|
||||
|
||||
#if defined(__BEOS__) && !defined(__ZETA__)
|
||||
/* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */
|
||||
# include <be/kernel/OS.h>
|
||||
static inline void testProcess_usleep(unsigned int msec)
|
||||
{
|
||||
snooze(msec);
|
||||
}
|
||||
#else
|
||||
# define testProcess_usleep usleep
|
||||
#endif
|
||||
|
||||
int runChild(const char* cmd[], int state, int exception, int value,
|
||||
int share, int output, int delay, double timeout, int poll,
|
||||
int repeat, int disown);
|
||||
|
@ -76,6 +87,9 @@ int test4(int argc, const char* argv[])
|
|||
#if defined(_WIN32)
|
||||
/* Avoid error diagnostic popups since we are crashing on purpose. */
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
|
||||
#elif defined(__BEOS__)
|
||||
/* Avoid error diagnostic popups since we are crashing on purpose. */
|
||||
disable_debugger(1);
|
||||
#endif
|
||||
(void)argc; (void)argv;
|
||||
fprintf(stdout, "Output before crash on stdout from crash test.\n");
|
||||
|
@ -264,7 +278,7 @@ int runChild2(kwsysProcess* kp,
|
|||
#if defined(_WIN32)
|
||||
Sleep(100);
|
||||
#else
|
||||
usleep(100000);
|
||||
testProcess_usleep(100000);
|
||||
#endif
|
||||
}
|
||||
if(delay)
|
||||
|
|
Loading…
Reference in New Issue