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