interim update for pio

- improved qse_pio_wait but not finished it yet
This commit is contained in:
hyung-hwan 2009-01-13 05:26:36 +00:00
parent cf09e22560
commit 8d794c7c73
3 changed files with 170 additions and 48 deletions

View File

@ -43,6 +43,12 @@ enum qse_pio_open_flag_t
QSE_PIO_SHELL = (1 << 11)
};
enum qse_pio_wait_flag_t
{
QSE_PIO_NOWAIT = (1 << 0),
QSE_PIO_IGNINTR = (1 << 1)
};
enum qse_pio_hid_t
{
QSE_PIO_IN = 0,
@ -55,11 +61,14 @@ typedef enum qse_pio_hid_t qse_pio_hid_t;
#ifdef _WIN32
/* <winnt.h> => typedef PVOID HANDLE; */
typedef void* qse_pio_hnd_t;
typedef int qse_pio_pid_t; /* TODO */
typedef void* qse_pio_pid_t;
# define QSE_PIO_HND_NIL ((qse_pio_hnd_t)QSE_NULL)
# define QSE_PIO_PID_NIL ((qse_pio_pid_t)QSE_NULL)
#else
typedef int qse_pio_hnd_t;
typedef int qse_pio_pid_t;
# define QSE_PIO_HND_NIL ((qse_pio_hnd_t)-1)
# define QSE_PIO_PID_NIL ((qse_pio_hnd_t)-1)
#endif
typedef struct qse_pio_t qse_pio_t;
@ -73,6 +82,7 @@ struct qse_pio_t
#define QSE_PIO_MMGR(pio) ((pio)->mmgr)
#define QSE_PIO_HANDLE(pio,hid) ((pio)->handle[hid])
#define QSE_PIO_CHILD(pio) ((pio)->child)
#ifdef __cplusplus
extern "C" {
@ -80,7 +90,7 @@ extern "C" {
/****f* qse.cmn.pio/qse_pio_open
* NAME
* qse_pio_open - open a pipe to a child process
* qse_pio_open - open pipes to a child process
*
* DESCRIPTION
* QSE_PIO_SHELL drives the function to execute the command via /bin/sh.
@ -98,7 +108,7 @@ qse_pio_t* qse_pio_open (
/****f* qse.cmn.pio/qse_pio_close
* NAME
* qse_pio_close - close a pipe
* qse_pio_close - close pipes to a child process
*
* SYNOPSIS
*/
@ -107,24 +117,27 @@ void qse_pio_close (
);
/******/
/****f* qse.cmn/pio/qse_pio_init
* NAME
* qse_pio_init - initialize pipes to a child process
*
* SYNOPSIS
*/
qse_pio_t* qse_pio_init (
qse_pio_t* pio,
qse_mmgr_t* mmgr,
const qse_char_t* path,
int flags
);
/******/
void qse_pio_fini (
qse_pio_t* pio
);
/****f* qse.cmn.pio/qse_pio_wait
/****f* qse.cmn/pio/qse_pio_fini
* NAME
* qse_pio_wait - wait for a child process
* qse_pio_fini - finalize pipes to a child process
*
* SYNOPSIS
*/
int qse_pio_wait (
void qse_pio_fini (
qse_pio_t* pio
);
/******/
@ -141,6 +154,17 @@ qse_pio_hnd_t qse_pio_gethandle (
);
/******/
/****f* qse.cmn.pio/qse_pio_getchild
* NAME
* qse_pio_getchild - get the PID of a child process
*
* SYNOPSIS
*/
qse_pio_pid_t qse_pio_getchild (
qse_pio_t* pio
);
/******/
/****f* qse.cmn.pio/qse_pio_read
* NAME
* qse_pio_read - read data
@ -185,6 +209,18 @@ void qse_pio_end (
);
/******/
/****f* qse.cmn.pio/qse_pio_wait
* NAME
* qse_pio_wait - wait for a child process
*
* SYNOPSIS
*/
int qse_pio_wait (
qse_pio_t* pio,
int flags
);
/******/
#ifdef __cplusplus
}
#endif

View File

@ -27,8 +27,11 @@
# include "syscall.h"
# include <fcntl.h>
# include <errno.h>
# include <sys/wait.h>
#endif
#define CHILD_EXIT_CODE 128
qse_pio_t* qse_pio_open (
qse_mmgr_t* mmgr, qse_size_t ext,
const qse_char_t* path, int flags)
@ -86,7 +89,9 @@ qse_pio_t* qse_pio_init (
#ifdef _WIN32
/* TODO: XXXXXXXXXXXXXXXXX */
http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx
#else
if (flags & QSE_PIO_WRITEIN)
{
if (QSE_PIPE(&handle[0]) == -1) goto oops;
@ -298,7 +303,7 @@ qse_pio_t* qse_pio_init (
}
child_oops:
QSE_EXIT(127);
QSE_EXIT (CHILD_EXIT_CODE);
}
/* parent */
@ -352,44 +357,10 @@ oops:
void qse_pio_fini (qse_pio_t* pio)
{
#ifdef _WIN32
CloseHandle (pio->handle);
#else
int i, status;
qse_pio_end (pio, QSE_PIO_IN);
qse_pio_end (pio, QSE_PIO_OUT);
qse_pio_end (pio, QSE_PIO_ERR);
while (QSE_WAITPID (pio->child, &status, 0) == -1)
{
if (errno != EINTR) break;
}
#endif
}
int qse_pio_wait (qse_pio_t* pio)
{
int status;
#if 0
if (opt & QSE_PIO_NOWAIT)
{
opt |= WNOHANG;
}
while (1)
{
n = QSE_WAITPID (pio->child, &status, opt);
if (n == 0) break;
/* TODO: .... */
}
output => return code...
output => termination cause...
#endif
return -1;
qse_pio_wait (pio, QSE_PIO_IGNINTR);
}
qse_pio_hnd_t qse_pio_gethandle (qse_pio_t* pio, qse_pio_hid_t hid)
@ -397,6 +368,11 @@ qse_pio_hnd_t qse_pio_gethandle (qse_pio_t* pio, qse_pio_hid_t hid)
return pio->handle[hid];
}
qse_pio_pid_t qse_pio_getchild (qse_pio_t* pio)
{
return pio->child;
}
qse_ssize_t qse_pio_read (
qse_pio_t* pio, void* buf, qse_size_t size, qse_pio_hid_t hid)
{
@ -445,3 +421,87 @@ void qse_pio_end (qse_pio_t* pio, qse_pio_hid_t hid)
pio->handle[hid] = QSE_PIO_HND_NIL;
}
}
/*
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;
WaitForSingleObject (pio->child, -1);
if (GetExitCodeProcess (pio->child, &ec) == -1)
/* close handle here to emulate waitpid() as much as possible. */
CloseHandle (pio->child);
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 (flags & QSE_PIO_NOWAIT) opt |= WNOHANG;
while (1)
{
int n = QSE_WAITPID (pio->child, &status, opt);
qse_printf (QSE_T("n=%d,pio->child=%d,errno=%d,ECHILD=%d\n"), n, pio->child, errno, ECHILD);
if (n == -1)
{
if (errno == ECHILD)
{
/* 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;
ret = -1; /* OR ECHILD / QSE_PIO_ECHILD */
break;
}
if (errno != EINTR || !(flags & QSE_PIO_IGNINTR)) break;
}
if (n == 0)
{
/* when WNOHANG is not specified, 0 can't be returned */
QSE_ASSERT (flags & QSE_PIO_NOWAIT);
ret = -2;
/* the child process is still alive */
break;
}
if (n == pio->child)
{
if (WIFEXITED(status))
{
/* the child process ended normally */
ret = WEXITSTATUS(status);
}
else if (WIFSIGNALED(status))
{
/* the child process was killed by a signal */
ret = 255 + WTERMSIG (status);
}
/* not interested in WIFSTOPPED & WIFCONTINUED */
pio->child = QSE_PIO_PID_NIL;
break;
}
}
return ret;
#endif
}

View File

@ -53,6 +53,7 @@ static int pio1 (const qse_char_t* cmd, int oflags, qse_pio_hid_t rhid)
return 0;
}
static int test1 (void)
{
return pio1 (QSE_T("ls -laF"), QSE_PIO_READOUT|QSE_PIO_WRITEIN|QSE_PIO_SHELL, QSE_PIO_OUT);
@ -65,8 +66,32 @@ static int test2 (void)
static int test3 (void)
{
//return pio1 (QSE_T("/bin/ls -laF"), QSE_PIO_READERR|QSE_PIO_OUTTOERR|QSE_PIO_WRITEIN, QSE_PIO_ERR);
return pio1 (QSE_T("\"/bin/ls\" -laF"), QSE_PIO_READERR|QSE_PIO_OUTTOERR|QSE_PIO_WRITEIN, QSE_PIO_ERR);
return pio1 (QSE_T("/bin/ls -laF"), QSE_PIO_READERR|QSE_PIO_OUTTOERR|QSE_PIO_WRITEIN, QSE_PIO_ERR);
}
static int test4 (void)
{
qse_pio_t* pio;
pio = qse_pio_open (
QSE_NULL,
0,
"ls -laF",
QSE_PIO_READOUT|QSE_PIO_READERR|QSE_PIO_WRITEIN
);
if (pio == QSE_NULL)
{
qse_printf (QSE_T("cannot open program through pipe\n"));
return -1;
}
{
int status;
sleep (5);
qse_printf (QSE_T("waitpid...%d\n"), (int)waitpid (-1, &status, 0));
}
qse_pio_close (pio);
}
int main ()
@ -80,6 +105,7 @@ int main ()
R (test1);
R (test2);
R (test3);
R (test4);
return 0;
}