added some pipe handling code

This commit is contained in:
hyung-hwan 2016-04-06 13:49:47 +00:00
parent 1e5c54cae0
commit 95563f11ce
4 changed files with 272 additions and 79 deletions

View File

@ -31,16 +31,107 @@
#include <fcntl.h>
#include <errno.h>
static int pro_make (stio_dev_t* dev, void* ctx)
{
stio_dev_pro_t* pro = (stio_dev_pro_t*)dev;
stio_dev_pro_make_t* arg = (stio_dev_pro_make_t*)ctx;
stio_syshnd_t hnd[6];
int i, minidx = -1, maxidx = -1;
if (arg->flags & STIO_DEV_PRO_WRITEIN)
static stio_dev_pro_t* make_sibling (stio_t* stio, stio_syshnd_t handle);
/* ========================================================================= */
static pid_t standard_fork_and_exec (stio_dev_pro_t* rdev, int pfds[], stio_dev_pro_make_t* info)
{
pid_t pid;
pid = fork ();
if (fork() == -1)
{
if (pipe(&hnd[0]) == -1)
rdev->stio->errnum = stio_syserrtoerrnum(errno);
return -1;
}
if (pid == 0)
{
stio_syshnd_t devnull = STIO_SYSHND_INVALID;
/* TODO: close all uneeded fds */
if (info->flags & STIO_DEV_PRO_WRITEIN)
{
/* child should read */
close (pfds[1]);
pfds[1] = STIO_SYSHND_INVALID;
/* let the pipe be standard input */
if (dup2 (pfds[0], 0) <= -1) goto child_oops;
close (pfds[0]);
pfds[0] = STIO_SYSHND_INVALID;
}
if (info->flags & STIO_DEV_PRO_READOUT)
{
/* child should write */
close (pfds[2]);
pfds[2] = STIO_SYSHND_INVALID;
if (dup2(pfds[3], 1) == -1) goto child_oops;
if (info->flags & STIO_DEV_PRO_ERRTOOUT)
{
if (dup2(pfds[3], 2) == -1) goto child_oops;
}
close (pfds[3]);
pfds[3] = STIO_SYSHND_INVALID;
}
if (info->flags & STIO_DEV_PRO_READERR)
{
close (pfds[4]);
pfds[4] = STIO_SYSHND_INVALID;
if (dup2(pfds[5], 2) == -1) goto child_oops;
if (info->flags & STIO_DEV_PRO_OUTTOERR)
{
if (dup2(pfds[5], 1) == -1) goto child_oops;
}
close (pfds[5]);
pfds[5] = STIO_SYSHND_INVALID;
}
if ((info->flags & STIO_DEV_PRO_INTONUL) ||
(info->flags & STIO_DEV_PRO_OUTTONUL) ||
(info->flags & STIO_DEV_PRO_ERRTONUL))
{
#if defined(O_LARGEFILE)
devnull = open ("/dev/null", O_RDWR | O_LARGEFILE, 0);
#else
devnull = open ("/dev/null", O_RDWR, 0);
#endif
if (devnull == STIO_SYSHND_INVALID) goto child_oops;
}
//execv (param->argv[0], param->argv);
child_oops:
if (devnull != STIO_SYSHND_INVALID) close(devnull);
_exit (128);
}
return pid;
}
static int dev_pro_make (stio_dev_t* dev, void* ctx)
{
stio_dev_pro_t* rdev = (stio_dev_pro_t*)dev;
stio_dev_pro_make_t* info = (stio_dev_pro_make_t*)ctx;
stio_syshnd_t pfds[6];
int i, minidx = -1, maxidx = -1;
pid_t pid;
if (info->flags & STIO_DEV_PRO_WRITEIN)
{
if (pipe(&pfds[0]) == -1)
{
dev->stio->errnum = stio_syserrtoerrnum(errno);
goto oops;
@ -48,9 +139,9 @@ static int pro_make (stio_dev_t* dev, void* ctx)
minidx = 0; maxidx = 1;
}
if (arg->flags & STIO_DEV_PRO_READOUT)
if (info->flags & STIO_DEV_PRO_READOUT)
{
if (pipe(&hnd[2]) == -1)
if (pipe(&pfds[2]) == -1)
{
dev->stio->errnum = stio_syserrtoerrnum(errno);
goto oops;
@ -59,9 +150,9 @@ static int pro_make (stio_dev_t* dev, void* ctx)
maxidx = 3;
}
if (arg->flags & STIO_DEV_PRO_READERR)
if (info->flags & STIO_DEV_PRO_READERR)
{
if (pipe(&hnd[4]) == -1)
if (pipe(&pfds[4]) == -1)
{
dev->stio->errnum = stio_syserrtoerrnum(errno);
goto oops;
@ -76,9 +167,14 @@ static int pro_make (stio_dev_t* dev, void* ctx)
goto oops;
}
/* TODO: fork and exec... */
/* TODO: more advanced fork and exec .. */
pid = standard_fork_and_exec (rdev, pfds, info);
if (pid <= -1) goto oops;
if (arg->flags & STIO_DEV_PRO_WRITEIN)
rdev->child_pid = pid;
/* this is the parent process */
if (info->flags & STIO_DEV_PRO_WRITEIN)
{
/*
* 012345
@ -86,11 +182,11 @@ static int pro_make (stio_dev_t* dev, void* ctx)
* X
* WRITE => 1
*/
close (hnd[0]);
hnd[0] = STIO_SYSHND_INVALID;
close (pfds[0]);
pfds[0] = STIO_SYSHND_INVALID;
}
if (arg->flags & STIO_DEV_PRO_READOUT)
if (info->flags & STIO_DEV_PRO_READOUT)
{
/*
* 012345
@ -98,11 +194,11 @@ static int pro_make (stio_dev_t* dev, void* ctx)
* X
* READ => 2
*/
close (hnd[3]);
hnd[3] = STIO_SYSHND_INVALID;
close (pfds[3]);
pfds[3] = STIO_SYSHND_INVALID;
}
if (arg->flags & STIO_DEV_PRO_READERR)
if (info->flags & STIO_DEV_PRO_READERR)
{
/*
* 012345
@ -110,31 +206,84 @@ static int pro_make (stio_dev_t* dev, void* ctx)
* X
* READ => 4
*/
close (hnd[5]);
hnd[5] = STIO_SYSHND_INVALID;
close (pfds[5]);
pfds[5] = STIO_SYSHND_INVALID;
}
if (stio_makesyshndasync (pro->stio, hnd[1]) <= -1 ||
stio_makesyshndasync (pro->stio, hnd[2]) <= -1 ||
stio_makesyshndasync (pro->stio, hnd[4]) <= -1) goto oops;
if (stio_makesyshndasync (dev->stio, pfds[1]) <= -1 ||
stio_makesyshndasync (dev->stio, pfds[2]) <= -1 ||
stio_makesyshndasync (dev->stio, pfds[4]) <= -1) goto oops;
if (pfds[2] != STIO_SYSHND_INVALID)
{
rdev->sibling[0] = make_sibling (dev->stio, pfds[2]);
if (!rdev->sibling[0]) goto oops;
pfds[2] = STIO_SYSHND_INVALID;
}
if (pfds[4] != STIO_SYSHND_INVALID)
{
rdev->sibling[1] = make_sibling (dev->stio, pfds[4]);
if (!rdev->sibling[1])
{
if (rdev->sibling[0])
{
stio_dev_pro_kill (rdev->sibling[0]);
rdev->sibling[0] = STIO_NULL;
}
goto oops;
}
pfds[4] = STIO_SYSHND_INVALID;
}
rdev->pfd = pfds[1];
return 0;
oops:
for (i = minidx; i < maxidx; i++)
{
if (hnd[i] != STIO_SYSHND_INVALID) close (hnd[i]);
if (pfds[i] != STIO_SYSHND_INVALID) close (pfds[i]);
}
return -1;
}
static void pro_kill (stio_dev_t* dev)
static int dev_pro_make_sibling (stio_dev_t* dev, void* ctx)
{
stio_dev_pro_t* rdev = (stio_dev_pro_t*)dev;
stio_syshnd_t* handle = (stio_syshnd_t*)ctx;
rdev->pfd = *handle;
if (stio_makesyshndasync (rdev->stio, rdev->pfd) <= -1) return -1;
return 0;
}
static int pro_read (stio_dev_t* dev, void* buf, stio_iolen_t* len)
static void dev_pro_kill (stio_dev_t* dev)
{
stio_dev_pro_t* rdev = (stio_dev_pro_t*)dev;
if (rdev->pfd != STIO_SYSHND_INVALID)
{
close (rdev->pfd);
rdev->pfd = STIO_SYSHND_INVALID;
}
if (rdev->sibling[0])
{
stio_dev_pro_kill (rdev->sibling[0]);
rdev->sibling[0] = STIO_NULL;
}
if (rdev->sibling[1])
{
stio_dev_pro_kill (rdev->sibling[1]);
rdev->sibling[1] = STIO_NULL;
}
}
static int dev_pro_read (stio_dev_t* dev, void* buf, stio_iolen_t* len, stio_devadr_t* srcadr)
{
stio_dev_pro_t* pro = (stio_dev_pro_t*)dev;
ssize_t x;
@ -152,33 +301,61 @@ static int pro_read (stio_dev_t* dev, void* buf, stio_iolen_t* len)
return 1;
}
static int pro_write (stio_dev_t* dev, const void* data, stio_iolen_t* len)
static int dev_pro_write (stio_dev_t* dev, const void* data, stio_iolen_t* len, const stio_devadr_t* dstadr)
{
return -1;
}
static stio_syshnd_t pro_getsyshnd (stio_dev_t* dev)
static stio_syshnd_t dev_pro_getsyshnd (stio_dev_t* dev)
{
stio_dev_pro_t* pro = (stio_dev_pro_t*)dev;
return (stio_syshnd_t)pro->pfd;
}
static int pro_ioctl (stio_dev_t* dev, int cmd, void* arg)
static int dev_pro_ioctl (stio_dev_t* dev, int cmd, void* arg)
{
/*
switch (cmd)
{
case STIO_DEV_PRO_KILL
case STIO_DEV_PRO_CLOSEIN:
case STIO_DEV_PRO_CLOSEOUT:
case STIO_DEV_PROC_CLOSEERR:
}
*/
return 0;
}
static stio_dev_mth_t pro_mth =
static stio_dev_mth_t dev_pro_methods =
{
pro_make,
pro_kill,
pro_getsyshnd,
pro_read,
pro_write,
pro_ioctl
dev_pro_make,
dev_pro_kill,
dev_pro_getsyshnd,
dev_pro_read,
dev_pro_write,
dev_pro_ioctl
};
static stio_dev_mth_t dev_pro_methods_sibling =
{
dev_pro_make_sibling,
dev_pro_kill,
dev_pro_getsyshnd,
dev_pro_read,
dev_pro_write,
dev_pro_ioctl
};
/* ========================================================================= */
static int pro_ready (stio_dev_t* dev, int events)
{
stio_dev_pro_t* pro = (stio_dev_pro_t*)dev;
@ -211,22 +388,35 @@ static int pro_on_read (stio_dev_t* dev, const void* data, stio_iolen_t len, con
return pro->on_read (pro, data, len);
}
static int pro_on_write (stio_dev_t* dev, void* wrctx, const stio_devadr_t* dstadr)
static int pro_on_write (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_devadr_t* dstadr)
{
stio_dev_pro_t* pro = (stio_dev_pro_t*)dev;
return pro->on_write (pro, wrctx);
}
static stio_dev_evcb_t pro_evcb =
static stio_dev_evcb_t dev_pro_event_callbacks =
{
pro_ready,
pro_on_read,
pro_on_write
};
/* ========================================================================= */
static stio_dev_pro_t* make_sibling (stio_t* stio, stio_syshnd_t handle)
{
return (stio_dev_pro_t*)stio_makedev (
stio, STIO_SIZEOF(stio_dev_pro_t),
&dev_pro_methods_sibling, &dev_pro_event_callbacks, (void*)&handle);
}
stio_dev_pro_t* stio_dev_pro_make (stio_t* stio, stio_size_t xtnsize, const stio_dev_pro_make_t* data)
{
return (stio_dev_pro_t*)stio_makedev (stio, STIO_SIZEOF(stio_dev_pro_t) + xtnsize, &pro_mth, &pro_evcb, (void*)data);
return (stio_dev_pro_t*)stio_makedev (
stio, STIO_SIZEOF(stio_dev_pro_t) + xtnsize,
&dev_pro_methods, &dev_pro_event_callbacks, (void*)data);
}
void stio_dev_pro_kill (stio_dev_pro_t* pro)
@ -258,4 +448,5 @@ stio_dev_pro_t* stio_dev_pro_getdev (stio_dev_pro_t* pro, stio_dev_pro_type_t ty
pro->dev->stio = STIO_EINVAL;
return STIO_NULL;
}
#endif

View File

@ -48,10 +48,10 @@ struct stio_dev_pro_t
STIO_DEV_HEADERS;
stio_syshnd_t pfd;
/* bitwised-ORed of #stio_dev_pro_state_t enumerators */
stio_dev_pro_type_t type;
stio_intptr_t child_pid;
stio_dev_pro_t* sibling[2];
stio_dev_pro_on_read_t on_read;
@ -65,12 +65,17 @@ enum stio_dev_pro_make_flag_t
STIO_DEV_PRO_WRITEIN = (1 << 0),
STIO_DEV_PRO_READOUT = (1 << 1),
STIO_DEV_PRO_READERR = (1 << 2),
STIO_DEV_PRO_INTONUL = (1 << 3),
STIO_DEV_PRO_OUTTONUL = (1 << 4),
STIO_DEV_PRO_ERRTONUL = (1 << 5),
STUO_DEV_PRO_DROPIN = (1 << 6),
STUO_DEV_PRO_DROPOUT = (1 << 7),
STUO_DEV_PRO_DROPERR = (1 << 8)
STIO_DEV_PRO_ERRTOOUT = (1 << 3),
STIO_DEV_PRO_OUTTOERR = (1 << 4),
STIO_DEV_PRO_INTONUL = (1 << 5),
STIO_DEV_PRO_OUTTONUL = (1 << 6),
STIO_DEV_PRO_ERRTONUL = (1 << 7),
STUO_DEV_PRO_DROPIN = (1 << 8),
STUO_DEV_PRO_DROPOUT = (1 << 9),
STUO_DEV_PRO_DROPERR = (1 << 10)
};
typedef enum stio_dev_pro_make_flag_t stio_dev_pro_make_flag_t;
@ -100,7 +105,7 @@ STIO_EXPORT void stio_dev_pro_kill (
STIO_EXPORT int stio_dev_pro_write (
stio_dev_pro_t* pro,
const void* data,
stio_iolen_t len,
stio_iolen_t len,
void* wrctx
);

View File

@ -64,7 +64,7 @@ stio_sckhnd_t stio_openasyncsck (stio_t* stio, int domain, int type, int proto)
stio_sckhnd_t sck;
#if defined(_WIN32)
sck = WSASocket (domain, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED /*| WSA_FLAG_NO_HANDLE_INHERIT*/);
sck = WSASocket (domain, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT);
if (sck == STIO_SCKHND_INVALID)
{
/* stio_seterrnum (dev->stio, STIO_ESYSERR); or translate errno to stio errnum */
@ -78,13 +78,24 @@ stio_sckhnd_t stio_openasyncsck (stio_t* stio, int domain, int type, int proto)
return STIO_SCKHND_INVALID;
}
#if defined(FD_CLOEXEC)
{
int flags = fcntl (sck, F_GETFD, 0);
if (fcntl (sck, F_SETFD, flags | FD_CLOEXEC) == -1)
{
stio->errnum = stio_syserrtoerrnum(errno);
return STIO_SCKHND_INVALID;
}
}
#endif
if (stio_makesckasync (stio, sck) <= -1)
{
close (sck);
return STIO_SCKHND_INVALID;
}
/* TODO: set CLOEXEC if it's defined */
#endif
return sck;
@ -536,7 +547,7 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg)
return 0;
}
static stio_dev_mth_t dev_mth_sck_stateless =
static stio_dev_mth_t dev_sck_methods_stateless =
{
dev_sck_make,
dev_sck_kill,
@ -548,7 +559,7 @@ static stio_dev_mth_t dev_mth_sck_stateless =
};
static stio_dev_mth_t dev_mth_sck_stateful =
static stio_dev_mth_t dev_sck_methods_stateful =
{
dev_sck_make,
dev_sck_kill,
@ -791,14 +802,14 @@ static int dev_evcb_sck_on_write_stateless (stio_dev_t* dev, stio_iolen_t wrlen,
return rdev->on_write (rdev, wrlen, wrctx, dstadr->ptr);
}
static stio_dev_evcb_t dev_evcb_sck_stateful =
static stio_dev_evcb_t dev_sck_event_callbacks_stateful =
{
dev_evcb_sck_ready_stateful,
dev_evcb_sck_on_read_stateful,
dev_evcb_sck_on_write_stateful
};
static stio_dev_evcb_t dev_evcb_sck_stateless =
static stio_dev_evcb_t dev_sck_event_callbacks_stateless =
{
dev_evcb_sck_ready_stateless,
dev_evcb_sck_on_read_stateless,
@ -819,11 +830,15 @@ stio_dev_sck_t* stio_dev_sck_make (stio_t* stio, stio_size_t xtnsize, const stio
if (sck_type_map[info->type].extra_dev_capa & STIO_DEV_CAPA_STREAM) /* can't use the IS_STATEFUL() macro yet */
{
rdev = (stio_dev_sck_t*)stio_makedev (stio, STIO_SIZEOF(stio_dev_sck_t) + xtnsize, &dev_mth_sck_stateful, &dev_evcb_sck_stateful, (void*)info);
rdev = (stio_dev_sck_t*)stio_makedev (
stio, STIO_SIZEOF(stio_dev_sck_t) + xtnsize,
&dev_sck_methods_stateful, &dev_sck_event_callbacks_stateful, (void*)info);
}
else
{
rdev = (stio_dev_sck_t*)stio_makedev (stio, STIO_SIZEOF(stio_dev_sck_t) + xtnsize, &dev_mth_sck_stateless, &dev_evcb_sck_stateless, (void*)info);
rdev = (stio_dev_sck_t*)stio_makedev (
stio, STIO_SIZEOF(stio_dev_sck_t) + xtnsize,
&dev_sck_methods_stateless, &dev_sck_event_callbacks_stateless, (void*)info);
}
return rdev;

View File

@ -286,7 +286,7 @@ STIO_EXPORT int stio_dev_sck_listen (
STIO_EXPORT int stio_dev_sck_write (
stio_dev_sck_t* dev,
const void* data,
stio_iolen_t len,
stio_iolen_t len,
void* wrctx,
const stio_sckadr_t* dstadr
);
@ -294,7 +294,7 @@ STIO_EXPORT int stio_dev_sck_write (
STIO_EXPORT int stio_dev_sck_timedwrite (
stio_dev_sck_t* dev,
const void* data,
stio_iolen_t len,
stio_iolen_t len,
const stio_ntime_t* tmout,
void* wrctx,
const stio_sckadr_t* dstadr
@ -313,28 +313,10 @@ static STIO_INLINE int stio_dev_sck_read (stio_dev_sck_t* sck, int enabled)
return stio_dev_read ((stio_dev_t*)sck, enabled);
}
/*
static STIO_INLINE int stio_dev_sck_write (stio_dev_sck_t* sck, const void* data, stio_iolen_t len, void* wrctx, const stio_devadr_t* dstadr)
{
return stio_dev_write ((stio_dev_t*)sck, data, len, wrctx, STIO_NULL);
}
static STIO_INLINE int stio_dev_sck_timedwrite (stio_dev_sck_t* sck, const void* data, stio_iolen_t len, const stio_ntime_t* tmout, void* wrctx)
{
return stio_dev_timedwrite ((stio_dev_t*)sck, data, len, tmout, wrctx, STIO_NULL);
}
*/
#else
#define stio_dev_sck_halt(sck) stio_dev_halt((stio_dev_t*)sck)
#define stio_dev_sck_read(sck,enabled) stio_dev_read((stio_dev_t*)sck, enabled)
/*
#define stio_dev_sck_write(sck,data,len,wrctx) stio_dev_write((stio_dev_t*)sck, data, len, wrctx, STIO_NULL)
#define stio_dev_sck_timedwrite(sck,data,len,tmout,wrctx) stio_dev_timedwrite((stio_dev_t*)sck, data, len, tmout, wrctx, STIO_NULL)
*/
#endif