interim update for pio
- improved qse_pio_wait but not finished it yet
This commit is contained in:
parent
cf09e22560
commit
8d794c7c73
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user