improved error handling in mio_dev_make()

This commit is contained in:
hyung-hwan 2020-07-29 10:04:14 +00:00
parent 07e6a1ac70
commit f7c441b981
10 changed files with 59 additions and 31 deletions

View File

@ -312,6 +312,7 @@ mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, mio_dev_sck_bind_t* sck_bind, mi
break; break;
} }
info.m.options = MIO_DEV_SCK_MAKE_LENIENT;
info.m.on_write = listener_on_write; info.m.on_write = listener_on_write;
info.m.on_read = listener_on_read; info.m.on_read = listener_on_read;
info.m.on_connect = listener_on_connect; 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; if (mio_dev_sck_bind(htts->lsck, sck_bind) <= -1) goto oops;
MIO_MEMSET (&info, 0, MIO_SIZEOF(info)); MIO_MEMSET (&info, 0, MIO_SIZEOF(info));
info.l.options = MIO_DEV_SCK_LISTEN_LENIENT;
info.l.backlogs = 4096; info.l.backlogs = 4096;
MIO_INIT_NTIME (&info.l.accept_tmout, 5, 1); MIO_INIT_NTIME (&info.l.accept_tmout, 5, 1);
if (mio_dev_sck_listen(htts->lsck, &info.l) <= -1) goto oops; if (mio_dev_sck_listen(htts->lsck, &info.l) <= -1) goto oops;

View File

@ -324,6 +324,7 @@ static mio_dev_mth_t dev_mar_methods =
{ {
dev_mar_make, dev_mar_make,
dev_mar_kill, dev_mar_kill,
MIO_NULL,
dev_mar_getsyshnd, dev_mar_getsyshnd,
MIO_NULL, MIO_NULL,

View File

@ -287,7 +287,10 @@ typedef enum mio_dev_sck_type_t mio_dev_sck_type_t;
enum mio_dev_sck_make_option_t enum mio_dev_sck_make_option_t
{ {
/* import the system handle specified in the hnd field */ /* 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; 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; mio_ntime_t connect_tmout;
}; };
#if 0
enum mio_dev_sck_listen_option_t 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; 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; typedef struct mio_dev_sck_listen_t mio_dev_sck_listen_t;
struct 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; int backlogs;
mio_ntime_t accept_tmout; mio_ntime_t accept_tmout;
}; };

View File

@ -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* 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)) if (dev_size < MIO_SIZEOF(mio_dev_t))
{ {
mio_seterrnum (mio, MIO_EINVAL); 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); 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->mio = mio;
dev->dev_size = dev_size; 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; dev->cw_count = 0;
/* call the callback function first */ /* call the callback function first */
mio_seterrnum (mio, MIO_ENOERR); if (dev->dev_mth->make(dev, make_ctx) <= -1) goto oops;
if (dev->dev_mth->make(dev, make_ctx) <= -1)
{
if (mio->errnum == MIO_ENOERR) mio_seterrnum (mio, MIO_EDEVMAKE);
goto oops;
}
/* the make callback must not change these fields */ /* the make callback must not change these fields */
MIO_ASSERT (mio, dev->dev_mth == dev_mth); MIO_ASSERT (mio, dev->dev_mth == dev_mth);
@ -883,13 +883,12 @@ oops_after_make:
} }
} }
} }
return MIO_NULL;
} }
return MIO_NULL; return MIO_NULL;
oops: oops:
mio_freemem (mio, dev); if (dev) mio_freemem (mio, dev);
return MIO_NULL; return MIO_NULL;
} }

View File

@ -182,10 +182,12 @@ struct mio_dev_mth_t
*/ */
int (*kill) (mio_dev_t* dev, int force); 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() */ 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. /* 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. * when returning 1, *len must be sent to the length of data read.

View File

@ -350,6 +350,7 @@ static mio_dev_mth_t dev_pipe_methods =
{ {
dev_pipe_make_master, dev_pipe_make_master,
dev_pipe_kill_master, dev_pipe_kill_master,
MIO_NULL,
dev_pipe_getsyshnd, dev_pipe_getsyshnd,
MIO_NULL, MIO_NULL,
@ -362,6 +363,7 @@ static mio_dev_mth_t dev_pipe_methods_slave =
{ {
dev_pipe_make_slave, dev_pipe_make_slave,
dev_pipe_kill_slave, dev_pipe_kill_slave,
MIO_NULL,
dev_pipe_getsyshnd_slave, dev_pipe_getsyshnd_slave,
dev_pipe_read_slave, dev_pipe_read_slave,

View File

@ -730,6 +730,7 @@ static mio_dev_mth_t dev_pro_methods =
{ {
dev_pro_make_master, dev_pro_make_master,
dev_pro_kill_master, dev_pro_kill_master,
MIO_NULL,
dev_pro_getsyshnd, dev_pro_getsyshnd,
MIO_NULL, /* read */ MIO_NULL, /* read */
@ -743,6 +744,7 @@ static mio_dev_mth_t dev_pro_methods_slave =
{ {
dev_pro_make_slave, dev_pro_make_slave,
dev_pro_kill_slave, dev_pro_kill_slave,
MIO_NULL,
dev_pro_getsyshnd_slave, dev_pro_getsyshnd_slave,
dev_pro_read_slave, dev_pro_read_slave,

View File

@ -32,6 +32,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include <string.h> /* strerror */
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
@ -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); 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->on_raw_accept = arg->on_raw_accept;
rdev->type = arg->type; rdev->type = arg->type;
if (arg->options & MIO_DEV_SCK_MAKE_LENIENT) rdev->state |= MIO_DEV_SCK_LENIENT;
return 0; return 0;
oops: oops:
@ -423,12 +426,24 @@ static int dev_sck_make_client (mio_dev_t* dev, void* ctx)
rdev->tmrjob_index = MIO_TMRIDX_INVALID; rdev->tmrjob_index = MIO_TMRIDX_INVALID;
rdev->side_chan = MIO_SYSHND_INVALID; rdev->side_chan = MIO_SYSHND_INVALID;
/*if (mio_makesyshndasync(mio, rdev->hnd) <= -1 || 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_makesyshndcloexec(mio, rdev->hnd) <= -1) goto oops;
*/
mio_makesyshndasync(mio, rdev->hnd);
mio_makesyshndcloexec(mio, rdev->hnd);
return 0; 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) 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; 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); MIO_DEV_SCK_SET_PROGRESS (rdev, MIO_DEV_SCK_LISTENING);
return 0; return 0;
@ -1316,6 +1330,7 @@ static mio_dev_mth_t dev_sck_methods_stateless =
{ {
dev_sck_make, dev_sck_make,
dev_sck_kill, dev_sck_kill,
MIO_NULL,
dev_sck_getsyshnd, dev_sck_getsyshnd,
dev_sck_read_stateless, dev_sck_read_stateless,
@ -1330,6 +1345,7 @@ static mio_dev_mth_t dev_sck_methods_stateful =
{ {
dev_sck_make, dev_sck_make,
dev_sck_kill, dev_sck_kill,
MIO_NULL,
dev_sck_getsyshnd, dev_sck_getsyshnd,
dev_sck_read_stateful, dev_sck_read_stateful,
@ -1343,6 +1359,7 @@ static mio_dev_mth_t dev_mth_clisck =
{ {
dev_sck_make_client, dev_sck_make_client,
dev_sck_kill, dev_sck_kill,
dev_sck_fail_before_make_client,
dev_sck_getsyshnd, dev_sck_getsyshnd,
dev_sck_read_stateful, 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); clidev = (mio_dev_sck_t*)mio_dev_make(mio, rdev->dev_size, &dev_mth_clisck, rdev->dev_evcb, &clisck);
if (MIO_UNLIKELY(!clidev)) 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)); 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; return -1;
} }
@ -1925,9 +1942,8 @@ printf ("unable wrong packet size... \n");
{ {
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"); printf ("unable to accept new client connection %d\n", qxmsg->syshnd);
close (qxmsg->syshnd); return (rdev->state & MIO_DEV_SCK_LENIENT)? 0: -1;
return -1;
} }
} }
else else

View File

@ -80,7 +80,7 @@ int mio_makesyshndasync (mio_t* mio, mio_syshnd_t hnd)
if ((flags = fcntl(hnd, F_GETFL, 0)) <= -1 || if ((flags = fcntl(hnd, F_GETFL, 0)) <= -1 ||
fcntl(hnd, F_SETFL, flags | O_NONBLOCK) <= -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); mio_seterrwithsyserr (mio, 0, errno);
return -1; return -1;
} }
@ -100,7 +100,7 @@ int mio_makesyshndcloexec (mio_t* mio, mio_syshnd_t hnd)
if ((flags = fcntl(hnd, F_GETFD, 0)) <= -1 || if ((flags = fcntl(hnd, F_GETFD, 0)) <= -1 ||
fcntl(hnd, F_SETFD, flags | FD_CLOEXEC) <= -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); mio_seterrwithsyserr (mio, 0, errno);
return -1; return -1;
} }

View File

@ -510,6 +510,7 @@ static mio_dev_mth_t dev_thr_methods =
{ {
dev_thr_make_master, dev_thr_make_master,
dev_thr_kill_master, dev_thr_kill_master,
MIO_NULL,
dev_thr_getsyshnd, dev_thr_getsyshnd,
MIO_NULL, MIO_NULL,
@ -522,6 +523,7 @@ static mio_dev_mth_t dev_thr_methods_slave =
{ {
dev_thr_make_slave, dev_thr_make_slave,
dev_thr_kill_slave, dev_thr_kill_slave,
MIO_NULL,
dev_thr_getsyshnd_slave, dev_thr_getsyshnd_slave,
dev_thr_read_slave, dev_thr_read_slave,