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]
|
[INSTALL]
|
||||||
|
|
||||||
|
@ -63,7 +63,10 @@ enum qse_pio_err_t
|
|||||||
{
|
{
|
||||||
QSE_PIO_ENOERR = 0,
|
QSE_PIO_ENOERR = 0,
|
||||||
QSE_PIO_ENOMEM, /* out of memory */
|
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;
|
typedef enum qse_pio_hid_t qse_pio_hid_t;
|
||||||
@ -269,6 +272,18 @@ void qse_pio_end (
|
|||||||
* NAME
|
* NAME
|
||||||
* qse_pio_wait - wait for a child process
|
* 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
|
* SYNOPSIS
|
||||||
*/
|
*/
|
||||||
int qse_pio_wait (
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -275,7 +275,7 @@ qse_fio_off_t qse_fio_seek (
|
|||||||
|
|
||||||
return (qse_fio_off_t)tmp;
|
return (qse_fio_off_t)tmp;
|
||||||
|
|
||||||
#elif defined(HAVE_LSEEK64)
|
#elif defined(QSE_LSEEK64)
|
||||||
return QSE_LSEEK64 (fio->handle, offset, seek_map[origin]);
|
return QSE_LSEEK64 (fio->handle, offset, seek_map[origin]);
|
||||||
#else
|
#else
|
||||||
return QSE_LSEEK (fio->handle, offset, seek_map[origin]);
|
return QSE_LSEEK (fio->handle, offset, seek_map[origin]);
|
||||||
|
@ -378,18 +378,31 @@ qse_ssize_t qse_pio_read (
|
|||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
DWORD count;
|
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 (size > QSE_TYPE_MAX(DWORD)) size = QSE_TYPE_MAX(DWORD);
|
||||||
if (ReadFile(pio->handle, buf, size, &count, QSE_NULL) == FALSE) return -1;
|
if (ReadFile(pio->handle, buf, size, &count, QSE_NULL) == FALSE) return -1;
|
||||||
return (qse_ssize_t)count;
|
return (qse_ssize_t)count;
|
||||||
#else
|
#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);
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,6 +411,18 @@ qse_ssize_t qse_pio_write (
|
|||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
DWORD count;
|
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 (size > QSE_TYPE_MAX(DWORD)) size = QSE_TYPE_MAX(DWORD);
|
||||||
if (WriteFile(pio->handle, data, size, &count, QSE_NULL) == FALSE) return -1;
|
if (WriteFile(pio->handle, data, size, &count, QSE_NULL) == FALSE) return -1;
|
||||||
return (qse_ssize_t)count;
|
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);
|
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
|
#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)
|
int qse_pio_wait (qse_pio_t* pio, int flags)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
DWORD ec;
|
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);
|
WaitForSingleObject (pio->child, -1);
|
||||||
if (GetExitCodeProcess (pio->child, &ec) == -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;
|
pio->child = QSE_PIO_PID_NIL;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
int status;
|
|
||||||
int opt = 0;
|
int opt = 0;
|
||||||
int ret = -1;
|
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;
|
if (flags & QSE_PIO_NOHANG) opt |= WNOHANG;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int n = QSE_WAITPID (pio->child, &status, opt);
|
int status, n;
|
||||||
|
|
||||||
|
n = QSE_WAITPID (pio->child, &status, opt);
|
||||||
|
|
||||||
if (n == -1)
|
if (n == -1)
|
||||||
{
|
{
|
||||||
@ -461,17 +495,17 @@ int qse_pio_wait (qse_pio_t* pio, int flags)
|
|||||||
{
|
{
|
||||||
/* most likely, the process has already been
|
/* most likely, the process has already been
|
||||||
* waitpid()ed on. */
|
* 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->child = QSE_PIO_PID_NIL;
|
||||||
pio->errnum = QSE_PIO_ECHILD;
|
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)
|
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 */
|
/* when WNOHANG is not specified, 0 can't be returned */
|
||||||
QSE_ASSERT (flags & QSE_PIO_NOHANG);
|
QSE_ASSERT (flags & QSE_PIO_NOHANG);
|
||||||
|
|
||||||
ret = -2;
|
ret = 255 + 1;
|
||||||
/* the child process is still alive */
|
/* the child process is still alive */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -494,10 +528,16 @@ int qse_pio_wait (qse_pio_t* pio, int flags)
|
|||||||
else if (WIFSIGNALED(status))
|
else if (WIFSIGNALED(status))
|
||||||
{
|
{
|
||||||
/* the child process was killed by a signal */
|
/* 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;
|
pio->child = QSE_PIO_PID_NIL;
|
||||||
break;
|
break;
|
||||||
@ -507,3 +547,33 @@ int qse_pio_wait (qse_pio_t* pio, int flags)
|
|||||||
return ret;
|
return ret;
|
||||||
#endif
|
#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
|
#ifdef HAVE_SYS_WAIT_H
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SIGNAL_H
|
||||||
|
#include <signal.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(QSE_USE_SYSCALL) && defined(HAVE_SYS_SYSCALL_H)
|
#if defined(QSE_USE_SYSCALL) && defined(HAVE_SYS_SYSCALL_H)
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
@ -117,6 +120,12 @@
|
|||||||
#define QSE_WAITPID(pid,status,options) waitpid(pid,status,options)
|
#define QSE_WAITPID(pid,status,options) waitpid(pid,status,options)
|
||||||
#endif
|
#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
|
#ifdef SYS_getpid
|
||||||
#define QSE_GETPID() syscall(SYS_getpid)
|
#define QSE_GETPID() syscall(SYS_getpid)
|
||||||
#else
|
#else
|
||||||
|
Loading…
Reference in New Issue
Block a user