From f7c441b98151dee34879cae267f6a98162704215 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Wed, 29 Jul 2020 10:04:14 +0000 Subject: [PATCH] improved error handling in mio_dev_make() --- mio/lib/http-svr.c | 2 +- mio/lib/mar.c | 1 + mio/lib/mio-sck.h | 10 +++++++--- mio/lib/mio.c | 23 +++++++++++------------ mio/lib/mio.h | 4 +++- mio/lib/pipe.c | 2 ++ mio/lib/pro.c | 2 ++ mio/lib/sck.c | 40 ++++++++++++++++++++++++++++------------ mio/lib/sys.c | 4 ++-- mio/lib/thr.c | 2 ++ 10 files changed, 59 insertions(+), 31 deletions(-) diff --git a/mio/lib/http-svr.c b/mio/lib/http-svr.c index f7d812a..bddaf77 100644 --- a/mio/lib/http-svr.c +++ b/mio/lib/http-svr.c @@ -312,6 +312,7 @@ mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, mio_dev_sck_bind_t* sck_bind, mi break; } + info.m.options = MIO_DEV_SCK_MAKE_LENIENT; info.m.on_write = listener_on_write; info.m.on_read = listener_on_read; info.m.on_connect = listener_on_connect; @@ -332,7 +333,6 @@ mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, mio_dev_sck_bind_t* sck_bind, mi if (mio_dev_sck_bind(htts->lsck, sck_bind) <= -1) goto oops; MIO_MEMSET (&info, 0, MIO_SIZEOF(info)); - info.l.options = MIO_DEV_SCK_LISTEN_LENIENT; info.l.backlogs = 4096; MIO_INIT_NTIME (&info.l.accept_tmout, 5, 1); if (mio_dev_sck_listen(htts->lsck, &info.l) <= -1) goto oops; diff --git a/mio/lib/mar.c b/mio/lib/mar.c index cb44872..6f20384 100644 --- a/mio/lib/mar.c +++ b/mio/lib/mar.c @@ -324,6 +324,7 @@ static mio_dev_mth_t dev_mar_methods = { dev_mar_make, dev_mar_kill, + MIO_NULL, dev_mar_getsyshnd, MIO_NULL, diff --git a/mio/lib/mio-sck.h b/mio/lib/mio-sck.h index d0e6eab..3498ad5 100644 --- a/mio/lib/mio-sck.h +++ b/mio/lib/mio-sck.h @@ -287,7 +287,10 @@ typedef enum mio_dev_sck_type_t mio_dev_sck_type_t; enum mio_dev_sck_make_option_t { /* import the system handle specified in the hnd field */ - MIO_DEV_SCK_MAKE_IMPSYSHND = (1 << 0) + MIO_DEV_SCK_MAKE_IMPSYSHND = (1 << 0), + + /* for now, accept failure doesn't affect the listing socket if this is set */ + MIO_DEV_SCK_MAKE_LENIENT = (1 << 1) }; typedef enum mio_dev_sck_make_option_t mio_dev_sck_make_option_t; @@ -346,16 +349,17 @@ struct mio_dev_sck_connect_t mio_ntime_t connect_tmout; }; +#if 0 enum mio_dev_sck_listen_option_t { - MIO_DEV_SCK_LISTEN_LENIENT = (1 << 0) /* for now, accept failure doesn't affect the listing socket if this is set */ }; typedef enum mio_dev_sck_listen_option_t mio_dev_sck_listen_option_t; +#endif typedef struct mio_dev_sck_listen_t mio_dev_sck_listen_t; struct mio_dev_sck_listen_t { - int options; + int options; /* no options as of now. set it to 0 */ int backlogs; mio_ntime_t accept_tmout; }; diff --git a/mio/lib/mio.c b/mio/lib/mio.c index 0296eca..e99d0c4 100644 --- a/mio/lib/mio.c +++ b/mio/lib/mio.c @@ -809,16 +809,21 @@ int mio_loop (mio_t* mio) mio_dev_t* mio_dev_make (mio_t* mio, mio_oow_t dev_size, mio_dev_mth_t* dev_mth, mio_dev_evcb_t* dev_evcb, void* make_ctx) { - mio_dev_t* dev; + mio_dev_t* dev = MIO_NULL; if (dev_size < MIO_SIZEOF(mio_dev_t)) { mio_seterrnum (mio, MIO_EINVAL); - return MIO_NULL; + if (dev_mth->fail_before_make) dev_mth->fail_before_make (make_ctx); + goto oops; } dev = (mio_dev_t*)mio_callocmem(mio, dev_size); - if (MIO_UNLIKELY(!dev)) return MIO_NULL; + if (MIO_UNLIKELY(!dev)) + { + if (dev_mth->fail_before_make) dev_mth->fail_before_make (make_ctx); + goto oops; + } dev->mio = mio; dev->dev_size = dev_size; @@ -833,12 +838,7 @@ mio_dev_t* mio_dev_make (mio_t* mio, mio_oow_t dev_size, mio_dev_mth_t* dev_mth, dev->cw_count = 0; /* call the callback function first */ - mio_seterrnum (mio, MIO_ENOERR); - if (dev->dev_mth->make(dev, make_ctx) <= -1) - { - if (mio->errnum == MIO_ENOERR) mio_seterrnum (mio, MIO_EDEVMAKE); - goto oops; - } + if (dev->dev_mth->make(dev, make_ctx) <= -1) goto oops; /* the make callback must not change these fields */ MIO_ASSERT (mio, dev->dev_mth == dev_mth); @@ -883,13 +883,12 @@ oops_after_make: } } } - - return MIO_NULL; } + return MIO_NULL; oops: - mio_freemem (mio, dev); + if (dev) mio_freemem (mio, dev); return MIO_NULL; } diff --git a/mio/lib/mio.h b/mio/lib/mio.h index a80d149..97f0bd6 100644 --- a/mio/lib/mio.h +++ b/mio/lib/mio.h @@ -182,10 +182,12 @@ struct mio_dev_mth_t */ int (*kill) (mio_dev_t* dev, int force); + /* optional. called if mio_dev_make() fails before the make() method is called */ + void (*fail_before_make) (void* ctx); + /* ------------------------------------------------------------------ */ mio_syshnd_t (*getsyshnd) (mio_dev_t* dev); /* mandatory. called in mio_dev_make() after successful make() */ - /* ------------------------------------------------------------------ */ /* return -1 on failure, 0 if no data is availble, 1 otherwise. * when returning 1, *len must be sent to the length of data read. diff --git a/mio/lib/pipe.c b/mio/lib/pipe.c index ffc568e..2e9208a 100644 --- a/mio/lib/pipe.c +++ b/mio/lib/pipe.c @@ -350,6 +350,7 @@ static mio_dev_mth_t dev_pipe_methods = { dev_pipe_make_master, dev_pipe_kill_master, + MIO_NULL, dev_pipe_getsyshnd, MIO_NULL, @@ -362,6 +363,7 @@ static mio_dev_mth_t dev_pipe_methods_slave = { dev_pipe_make_slave, dev_pipe_kill_slave, + MIO_NULL, dev_pipe_getsyshnd_slave, dev_pipe_read_slave, diff --git a/mio/lib/pro.c b/mio/lib/pro.c index 0b0337d..fd7cce3 100644 --- a/mio/lib/pro.c +++ b/mio/lib/pro.c @@ -730,6 +730,7 @@ static mio_dev_mth_t dev_pro_methods = { dev_pro_make_master, dev_pro_kill_master, + MIO_NULL, dev_pro_getsyshnd, MIO_NULL, /* read */ @@ -743,6 +744,7 @@ static mio_dev_mth_t dev_pro_methods_slave = { dev_pro_make_slave, dev_pro_kill_slave, + MIO_NULL, dev_pro_getsyshnd_slave, dev_pro_read_slave, diff --git a/mio/lib/sck.c b/mio/lib/sck.c index 9a56b28..c314660 100644 --- a/mio/lib/sck.c +++ b/mio/lib/sck.c @@ -32,6 +32,7 @@ #include #include #include +#include /* strerror */ #include #include @@ -79,7 +80,7 @@ /* ========================================================================= */ -static void close_async_socket (mio_t* mio, mio_syshnd_t sck) +static MIO_INLINE void close_async_socket (mio_t* mio, mio_syshnd_t sck) { close (sck); } @@ -399,6 +400,8 @@ static int dev_sck_make (mio_dev_t* dev, void* ctx) rdev->on_raw_accept = arg->on_raw_accept; rdev->type = arg->type; + if (arg->options & MIO_DEV_SCK_MAKE_LENIENT) rdev->state |= MIO_DEV_SCK_LENIENT; + return 0; oops: @@ -423,12 +426,24 @@ static int dev_sck_make_client (mio_dev_t* dev, void* ctx) rdev->tmrjob_index = MIO_TMRIDX_INVALID; rdev->side_chan = MIO_SYSHND_INVALID; -/*if (mio_makesyshndasync(mio, rdev->hnd) <= -1 || - mio_makesyshndcloexec(mio, rdev->hnd) <= -1) { printf ("cannot make sysnhnd async or cloexec %d\n", rdev->hnd); return -1; } - */ - mio_makesyshndasync(mio, rdev->hnd); - mio_makesyshndcloexec(mio, rdev->hnd); + if (mio_makesyshndasync(mio, rdev->hnd) <= -1 || + mio_makesyshndcloexec(mio, rdev->hnd) <= -1) goto oops; + return 0; + +oops: + if (rdev->hnd != MIO_SYSHND_INVALID) + { + close (rdev->hnd); + rdev->hnd = MIO_SYSHND_INVALID; + } + return -1; +} + +static void dev_sck_fail_before_make_client (void* ctx) +{ + mio_syshnd_t* clisckhnd = (mio_syshnd_t*)ctx; + close (*clisckhnd); } static int dev_sck_kill (mio_dev_t* dev, int force) @@ -1302,7 +1317,6 @@ fcntl (rdev->hnd, F_SETFL, flags | O_NONBLOCK); } rdev->tmout = lstn->accept_tmout; - if (lstn->options & MIO_DEV_SCK_LISTEN_LENIENT) rdev->state |= MIO_DEV_SCK_LENIENT; MIO_DEV_SCK_SET_PROGRESS (rdev, MIO_DEV_SCK_LISTENING); return 0; @@ -1316,6 +1330,7 @@ static mio_dev_mth_t dev_sck_methods_stateless = { dev_sck_make, dev_sck_kill, + MIO_NULL, dev_sck_getsyshnd, dev_sck_read_stateless, @@ -1330,6 +1345,7 @@ static mio_dev_mth_t dev_sck_methods_stateful = { dev_sck_make, dev_sck_kill, + MIO_NULL, dev_sck_getsyshnd, dev_sck_read_stateful, @@ -1343,6 +1359,7 @@ static mio_dev_mth_t dev_mth_clisck = { dev_sck_make_client, dev_sck_kill, + dev_sck_fail_before_make_client, dev_sck_getsyshnd, dev_sck_read_stateful, @@ -1469,8 +1486,8 @@ static int make_accepted_client_connection (mio_dev_sck_t* rdev, mio_syshnd_t cl clidev = (mio_dev_sck_t*)mio_dev_make(mio, rdev->dev_size, &dev_mth_clisck, rdev->dev_evcb, &clisck); if (MIO_UNLIKELY(!clidev)) { + /* [NOTE] 'clisck' is closed by callback methods called by mio_dev_make() upon failure */ MIO_DEBUG3 (mio, "SCK(%p) - unable to make a new accepted device for %d - %js\n", rdev, (int)clisck, mio_geterrmsg(mio)); - close (clisck); return -1; } @@ -1923,11 +1940,10 @@ printf ("unable wrong packet size... \n"); qxmsg = (mio_dev_sck_qxmsg_t*)data; if (qxmsg->cmd == MIO_DEV_SCK_QXMSG_NEWCONN) { - if (make_accepted_client_connection(rdev, qxmsg->syshnd, &qxmsg->remoteaddr, qxmsg->scktype) <= -1) + if (make_accepted_client_connection(rdev, qxmsg->syshnd, &qxmsg->remoteaddr, qxmsg->scktype) <= -1) { -printf ("unable to accept new client connection\n"); - close (qxmsg->syshnd); - return -1; +printf ("unable to accept new client connection %d\n", qxmsg->syshnd); + return (rdev->state & MIO_DEV_SCK_LENIENT)? 0: -1; } } else diff --git a/mio/lib/sys.c b/mio/lib/sys.c index a1b893f..eef38b5 100644 --- a/mio/lib/sys.c +++ b/mio/lib/sys.c @@ -80,7 +80,7 @@ int mio_makesyshndasync (mio_t* mio, mio_syshnd_t hnd) if ((flags = fcntl(hnd, F_GETFL, 0)) <= -1 || fcntl(hnd, F_SETFL, flags | O_NONBLOCK) <= -1) { -printf ("make sysnhd async error (%d)\n", hnd); +printf ("make sysnhd async error (%d) - errno %d\n", hnd, errno); mio_seterrwithsyserr (mio, 0, errno); return -1; } @@ -100,7 +100,7 @@ int mio_makesyshndcloexec (mio_t* mio, mio_syshnd_t hnd) if ((flags = fcntl(hnd, F_GETFD, 0)) <= -1 || fcntl(hnd, F_SETFD, flags | FD_CLOEXEC) <= -1) { -printf ("make sysnhd cloexec error (%d)\n", hnd); +printf ("make sysnhd cloexec error (%d) - errno %d\n", hnd, errno); mio_seterrwithsyserr (mio, 0, errno); return -1; } diff --git a/mio/lib/thr.c b/mio/lib/thr.c index 8c06758..14865c4 100644 --- a/mio/lib/thr.c +++ b/mio/lib/thr.c @@ -510,6 +510,7 @@ static mio_dev_mth_t dev_thr_methods = { dev_thr_make_master, dev_thr_kill_master, + MIO_NULL, dev_thr_getsyshnd, MIO_NULL, @@ -522,6 +523,7 @@ static mio_dev_mth_t dev_thr_methods_slave = { dev_thr_make_slave, dev_thr_kill_slave, + MIO_NULL, dev_thr_getsyshnd_slave, dev_thr_read_slave,