interim commit for qse_pio_t
- added QSE_KILL() - added qse_pio_kill() - enhanced qse_pio_wait()
This commit is contained in:
parent
31efbc7ecf
commit
f6dda99f51
@ -1,5 +1,5 @@
|
||||
|
||||
QSE is a script engine library designed to be embedded into an application.
|
||||
QSE provides a script engine for various scripting languages. It aims to produce a script engine framework that can be embedded into an application. A hosting application can access various aspects of the embedded script engine and vice versa.
|
||||
|
||||
[INSTALL]
|
||||
|
||||
|
@ -63,7 +63,10 @@ enum qse_pio_err_t
|
||||
{
|
||||
QSE_PIO_ENOERR = 0,
|
||||
QSE_PIO_ENOMEM, /* out of memory */
|
||||
QSE_PIO_ECHILD /* the child is not valid */
|
||||
QSE_PIO_ENOHND, /* no handle available */
|
||||
QSE_PIO_ECHILD, /* the child is not valid */
|
||||
QSE_PIO_EINTR, /* interrupted */
|
||||
QSE_PIO_ESYSCALL /* system call error */
|
||||
};
|
||||
|
||||
typedef enum qse_pio_hid_t qse_pio_hid_t;
|
||||
@ -269,6 +272,18 @@ void qse_pio_end (
|
||||
* NAME
|
||||
* qse_pio_wait - wait for a child process
|
||||
*
|
||||
* DESCRIPTION
|
||||
* QSE_PIO_IGNINTR causes the function to retry when the underlying system
|
||||
* call is interrupted.
|
||||
* When you specify QSE_PIO_NOHANG, the return value of 256 indicates that the
|
||||
* child process has not terminated. If the flag is not specified, 256 will
|
||||
* never be returned.
|
||||
*
|
||||
* RETURN
|
||||
* -1 on error, 256 if the child is still alive and QSE_PIO_NOHANG is specified,
|
||||
* a number between 0 and 255 inclusive if the child process terminates normally,
|
||||
* 256 + signal number if the child process is terminated by a signal.
|
||||
*
|
||||
* SYNOPSIS
|
||||
*/
|
||||
int qse_pio_wait (
|
||||
@ -277,6 +292,22 @@ int qse_pio_wait (
|
||||
);
|
||||
/******/
|
||||
|
||||
/****f* qse.cmn.pio/qse_pio_kill
|
||||
* NAME
|
||||
* qse_pio_kill - terminate the child process
|
||||
*
|
||||
* NOTES
|
||||
* You should know the danger of calling this function as the function can
|
||||
* kill a process that is not your child process if it has terminated but
|
||||
* there is a new process with the same process handle.
|
||||
*
|
||||
* SYNOPSIS
|
||||
*/
|
||||
int qse_pio_kill (
|
||||
qse_pio_t* pio
|
||||
);
|
||||
/******/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -275,7 +275,7 @@ qse_fio_off_t qse_fio_seek (
|
||||
|
||||
return (qse_fio_off_t)tmp;
|
||||
|
||||
#elif defined(HAVE_LSEEK64)
|
||||
#elif defined(QSE_LSEEK64)
|
||||
return QSE_LSEEK64 (fio->handle, offset, seek_map[origin]);
|
||||
#else
|
||||
return QSE_LSEEK (fio->handle, offset, seek_map[origin]);
|
||||
|
@ -378,18 +378,31 @@ qse_ssize_t qse_pio_read (
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD count;
|
||||
#else
|
||||
qse_ssize_t n;
|
||||
#endif
|
||||
|
||||
if (pio->handle[hid] == QSE_PIO_HND_NIL)
|
||||
{
|
||||
/* the stream is already closed */
|
||||
pio->errnum = QSE_PIO_ENOHND;
|
||||
return (qse_ssize_t)-1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (size > QSE_TYPE_MAX(DWORD)) size = QSE_TYPE_MAX(DWORD);
|
||||
if (ReadFile(pio->handle, buf, size, &count, QSE_NULL) == FALSE) return -1;
|
||||
return (qse_ssize_t)count;
|
||||
#else
|
||||
if (pio->handle[hid] == QSE_PIO_HND_NIL)
|
||||
{
|
||||
/* the stream is already closed */
|
||||
return (qse_ssize_t)-1;
|
||||
}
|
||||
|
||||
if (size > QSE_TYPE_MAX(size_t)) size = QSE_TYPE_MAX(size_t);
|
||||
return QSE_READ (pio->handle[hid], buf, size);
|
||||
n = QSE_READ (pio->handle[hid], buf, size);
|
||||
if (n == -1)
|
||||
{
|
||||
pio->errnum = (errno == EINTR)?
|
||||
QSE_PIO_EINTR: QSE_PIO_ESYSCALL;
|
||||
}
|
||||
return n;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -398,6 +411,18 @@ qse_ssize_t qse_pio_write (
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD count;
|
||||
#else
|
||||
qse_ssize_t n;
|
||||
#endif
|
||||
|
||||
if (pio->handle[hid] == QSE_PIO_HND_NIL)
|
||||
{
|
||||
/* the stream is already closed */
|
||||
pio->errnum = QSE_PIO_ENOHND;
|
||||
return (qse_ssize_t)-1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (size > QSE_TYPE_MAX(DWORD)) size = QSE_TYPE_MAX(DWORD);
|
||||
if (WriteFile(pio->handle, data, size, &count, QSE_NULL) == FALSE) return -1;
|
||||
return (qse_ssize_t)count;
|
||||
@ -409,7 +434,13 @@ qse_ssize_t qse_pio_write (
|
||||
}
|
||||
|
||||
if (size > QSE_TYPE_MAX(size_t)) size = QSE_TYPE_MAX(size_t);
|
||||
return QSE_WRITE (pio->handle[hid], data, size);
|
||||
n = QSE_WRITE (pio->handle[hid], data, size);
|
||||
if (n == -1)
|
||||
{
|
||||
pio->errnum = (errno == EINTR)?
|
||||
QSE_PIO_EINTR: QSE_PIO_ESYSCALL;
|
||||
}
|
||||
return n;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -422,19 +453,17 @@ void qse_pio_end (qse_pio_t* pio, qse_pio_hid_t hid)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
return -1 on error
|
||||
return -2 on no change
|
||||
return retcode on normal exit
|
||||
return 255+signal on kill.
|
||||
*/
|
||||
|
||||
int qse_pio_wait (qse_pio_t* pio, int flags)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD ec;
|
||||
|
||||
if (pio->child == QSE_PIO_PID_NIL) return -1;
|
||||
if (pio->child == QSE_PIO_PID_NIL)
|
||||
{
|
||||
|
||||
pio->errnum = QSE_PIO_ECHILD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
WaitForSingleObject (pio->child, -1);
|
||||
if (GetExitCodeProcess (pio->child, &ec) == -1)
|
||||
@ -443,17 +472,22 @@ int qse_pio_wait (qse_pio_t* pio, int flags)
|
||||
pio->child = QSE_PIO_PID_NIL;
|
||||
|
||||
#else
|
||||
int status;
|
||||
int opt = 0;
|
||||
int ret = -1;
|
||||
|
||||
if (pio->child == QSE_PIO_PID_NIL) return -1;
|
||||
if (pio->child == QSE_PIO_PID_NIL)
|
||||
{
|
||||
pio->errnum = QSE_PIO_ECHILD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & QSE_PIO_NOHANG) opt |= WNOHANG;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int n = QSE_WAITPID (pio->child, &status, opt);
|
||||
int status, n;
|
||||
|
||||
n = QSE_WAITPID (pio->child, &status, opt);
|
||||
|
||||
if (n == -1)
|
||||
{
|
||||
@ -461,17 +495,17 @@ int qse_pio_wait (qse_pio_t* pio, int flags)
|
||||
{
|
||||
/* most likely, the process has already been
|
||||
* waitpid()ed on. */
|
||||
|
||||
/* TODO: what should we do... ? */
|
||||
/* ??? TREAT AS NORMAL??? => cannot know exit code => TREAT AS ERROR but reset pio->child */
|
||||
|
||||
pio->child = QSE_PIO_PID_NIL;
|
||||
pio->errnum = QSE_PIO_ECHILD;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
else if (errno == EINTR)
|
||||
{
|
||||
if (flags & QSE_PIO_IGNINTR) continue;
|
||||
pio->errnum = QSE_PIO_EINTR;
|
||||
}
|
||||
else pio->errnum = QSE_PIO_ESYSCALL;
|
||||
|
||||
if (errno != EINTR || !(flags & QSE_PIO_IGNINTR)) break;
|
||||
break;
|
||||
}
|
||||
|
||||
if (n == 0)
|
||||
@ -479,7 +513,7 @@ int qse_pio_wait (qse_pio_t* pio, int flags)
|
||||
/* when WNOHANG is not specified, 0 can't be returned */
|
||||
QSE_ASSERT (flags & QSE_PIO_NOHANG);
|
||||
|
||||
ret = -2;
|
||||
ret = 255 + 1;
|
||||
/* the child process is still alive */
|
||||
break;
|
||||
}
|
||||
@ -494,10 +528,16 @@ int qse_pio_wait (qse_pio_t* pio, int flags)
|
||||
else if (WIFSIGNALED(status))
|
||||
{
|
||||
/* the child process was killed by a signal */
|
||||
ret = 255 + WTERMSIG (status);
|
||||
ret = 255 + 1 + WTERMSIG (status);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not interested in WIFSTOPPED & WIFCONTINUED.
|
||||
* in fact, this else block should not be reached
|
||||
* as WIFEXITED or WIFSIGNALED must be true.
|
||||
* anyhow, just set the return value to 0. */
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
/* not interested in WIFSTOPPED & WIFCONTINUED */
|
||||
|
||||
pio->child = QSE_PIO_PID_NIL;
|
||||
break;
|
||||
@ -507,3 +547,33 @@ int qse_pio_wait (qse_pio_t* pio, int flags)
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
int qse_pio_kill (qse_pio_t* pio)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DWORD n;
|
||||
#else
|
||||
int n;
|
||||
#endif
|
||||
|
||||
if (pio->child == QSE_PIO_PID_NIL)
|
||||
{
|
||||
pio->errnum = QSE_PIO_ECHILD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
/* 9 was chosen below to treat TerminateProcess as kill -KILL. */
|
||||
n = TerminateProcess (pio->child, 255 + 1 + 9);
|
||||
if (n == FALSE)
|
||||
{
|
||||
pio->errnum = QSE_PIO_SYSCALL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
n = QSE_KILL (pio->child, SIGKILL);
|
||||
if (n == -1) pio->errnum = QSE_PIO_ESYSCALL;
|
||||
return n;
|
||||
#endif
|
||||
}
|
||||
|
@ -12,6 +12,9 @@
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#if defined(QSE_USE_SYSCALL) && defined(HAVE_SYS_SYSCALL_H)
|
||||
#include <sys/syscall.h>
|
||||
@ -117,6 +120,12 @@
|
||||
#define QSE_WAITPID(pid,status,options) waitpid(pid,status,options)
|
||||
#endif
|
||||
|
||||
#ifdef SYS_kill
|
||||
#define QSE_KILL(pid,sig) syscall(SYS_kill,pid,sig)
|
||||
#else
|
||||
#define QSE_KILL(pid,sig) kill(pid,sig)
|
||||
#endif
|
||||
|
||||
#ifdef SYS_getpid
|
||||
#define QSE_GETPID() syscall(SYS_getpid)
|
||||
#else
|
||||
|
Loading…
Reference in New Issue
Block a user