interim commit for qse_pio_t

- added QSE_KILL()
- added qse_pio_kill()
- enhanced qse_pio_wait()
This commit is contained in:
hyung-hwan 2009-01-14 04:30:32 +00:00
parent 31efbc7ecf
commit f6dda99f51
5 changed files with 142 additions and 32 deletions

View File

@ -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]

View File

@ -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

View File

@ -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]);

View File

@ -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
}

View File

@ -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