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 <fcntl.h>
#include <errno.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); dev->stio->errnum = stio_syserrtoerrnum(errno);
goto oops; goto oops;
@ -48,9 +139,9 @@ static int pro_make (stio_dev_t* dev, void* ctx)
minidx = 0; maxidx = 1; 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); dev->stio->errnum = stio_syserrtoerrnum(errno);
goto oops; goto oops;
@ -59,9 +150,9 @@ static int pro_make (stio_dev_t* dev, void* ctx)
maxidx = 3; 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); dev->stio->errnum = stio_syserrtoerrnum(errno);
goto oops; goto oops;
@ -76,9 +167,14 @@ static int pro_make (stio_dev_t* dev, void* ctx)
goto oops; 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 * 012345
@ -86,11 +182,11 @@ static int pro_make (stio_dev_t* dev, void* ctx)
* X * X
* WRITE => 1 * WRITE => 1
*/ */
close (hnd[0]); close (pfds[0]);
hnd[0] = STIO_SYSHND_INVALID; pfds[0] = STIO_SYSHND_INVALID;
} }
if (arg->flags & STIO_DEV_PRO_READOUT) if (info->flags & STIO_DEV_PRO_READOUT)
{ {
/* /*
* 012345 * 012345
@ -98,11 +194,11 @@ static int pro_make (stio_dev_t* dev, void* ctx)
* X * X
* READ => 2 * READ => 2
*/ */
close (hnd[3]); close (pfds[3]);
hnd[3] = STIO_SYSHND_INVALID; pfds[3] = STIO_SYSHND_INVALID;
} }
if (arg->flags & STIO_DEV_PRO_READERR) if (info->flags & STIO_DEV_PRO_READERR)
{ {
/* /*
* 012345 * 012345
@ -110,31 +206,84 @@ static int pro_make (stio_dev_t* dev, void* ctx)
* X * X
* READ => 4 * READ => 4
*/ */
close (hnd[5]); close (pfds[5]);
hnd[5] = STIO_SYSHND_INVALID; pfds[5] = STIO_SYSHND_INVALID;
} }
if (stio_makesyshndasync (pro->stio, hnd[1]) <= -1 || if (stio_makesyshndasync (dev->stio, pfds[1]) <= -1 ||
stio_makesyshndasync (pro->stio, hnd[2]) <= -1 || stio_makesyshndasync (dev->stio, pfds[2]) <= -1 ||
stio_makesyshndasync (pro->stio, hnd[4]) <= -1) goto oops; 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; return 0;
oops: oops:
for (i = minidx; i < maxidx; i++) 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; return -1;
} }
static int dev_pro_make_sibling (stio_dev_t* dev, void* ctx)
static void pro_kill (stio_dev_t* dev)
{ {
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; stio_dev_pro_t* pro = (stio_dev_pro_t*)dev;
ssize_t x; ssize_t x;
@ -152,33 +301,61 @@ static int pro_read (stio_dev_t* dev, void* buf, stio_iolen_t* len)
return 1; 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; 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; stio_dev_pro_t* pro = (stio_dev_pro_t*)dev;
return (stio_syshnd_t)pro->pfd; 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; return 0;
} }
static stio_dev_mth_t pro_mth = static stio_dev_mth_t dev_pro_methods =
{ {
pro_make, dev_pro_make,
pro_kill, dev_pro_kill,
pro_getsyshnd, dev_pro_getsyshnd,
pro_read,
pro_write, dev_pro_read,
pro_ioctl 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) static int pro_ready (stio_dev_t* dev, int events)
{ {
stio_dev_pro_t* pro = (stio_dev_pro_t*)dev; 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); 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; stio_dev_pro_t* pro = (stio_dev_pro_t*)dev;
return pro->on_write (pro, wrctx); 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_ready,
pro_on_read, pro_on_read,
pro_on_write 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) 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) 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; pro->dev->stio = STIO_EINVAL;
return STIO_NULL; return STIO_NULL;
} }
#endif #endif

View File

@ -48,10 +48,10 @@ struct stio_dev_pro_t
STIO_DEV_HEADERS; STIO_DEV_HEADERS;
stio_syshnd_t pfd; stio_syshnd_t pfd;
/* bitwised-ORed of #stio_dev_pro_state_t enumerators */
stio_dev_pro_type_t type; stio_dev_pro_type_t type;
stio_intptr_t child_pid;
stio_dev_pro_t* sibling[2]; stio_dev_pro_t* sibling[2];
stio_dev_pro_on_read_t on_read; 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_WRITEIN = (1 << 0),
STIO_DEV_PRO_READOUT = (1 << 1), STIO_DEV_PRO_READOUT = (1 << 1),
STIO_DEV_PRO_READERR = (1 << 2), STIO_DEV_PRO_READERR = (1 << 2),
STIO_DEV_PRO_INTONUL = (1 << 3),
STIO_DEV_PRO_OUTTONUL = (1 << 4), STIO_DEV_PRO_ERRTOOUT = (1 << 3),
STIO_DEV_PRO_ERRTONUL = (1 << 5), STIO_DEV_PRO_OUTTOERR = (1 << 4),
STUO_DEV_PRO_DROPIN = (1 << 6),
STUO_DEV_PRO_DROPOUT = (1 << 7), STIO_DEV_PRO_INTONUL = (1 << 5),
STUO_DEV_PRO_DROPERR = (1 << 8) 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; typedef enum stio_dev_pro_make_flag_t stio_dev_pro_make_flag_t;

View File

@ -64,7 +64,7 @@ stio_sckhnd_t stio_openasyncsck (stio_t* stio, int domain, int type, int proto)
stio_sckhnd_t sck; stio_sckhnd_t sck;
#if defined(_WIN32) #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) if (sck == STIO_SCKHND_INVALID)
{ {
/* stio_seterrnum (dev->stio, STIO_ESYSERR); or translate errno to stio errnum */ /* 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; 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) if (stio_makesckasync (stio, sck) <= -1)
{ {
close (sck); close (sck);
return STIO_SCKHND_INVALID; return STIO_SCKHND_INVALID;
} }
/* TODO: set CLOEXEC if it's defined */
#endif #endif
return sck; return sck;
@ -536,7 +547,7 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg)
return 0; 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_make,
dev_sck_kill, 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_make,
dev_sck_kill, 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); 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_ready_stateful,
dev_evcb_sck_on_read_stateful, dev_evcb_sck_on_read_stateful,
dev_evcb_sck_on_write_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_ready_stateless,
dev_evcb_sck_on_read_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 */ 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 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; return rdev;

View File

@ -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); 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 #else
#define stio_dev_sck_halt(sck) stio_dev_halt((stio_dev_t*)sck) #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_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 #endif