fixed the premature EOF reporting caused by a file descriptor added without intention of input/output watching. as EPOLLHUP is always waited for, it caused early EOF reporting

This commit is contained in:
hyung-hwan 2020-05-24 19:29:35 +00:00
parent d622202db1
commit 8178d44ec0
4 changed files with 76 additions and 15 deletions

View File

@ -1045,7 +1045,7 @@ int mio_dev_watch (mio_dev_t* dev, mio_dev_watch_cmd_t cmd, int events)
if (dev->dev_cap & MIO_DEV_CAP_VIRTUAL) return 0;
/*ev.data.ptr = dev;*/
dev_cap = dev->dev_cap & ~(DEV_CAP_ALL_WATCHED);
dev_cap = dev->dev_cap & ~(DEV_CAP_ALL_WATCHED | MIO_DEV_CAP_WATCH_SUSPENDED); /* UGLY to use MIO_DEV_CAP_WATCH_SUSPENDED here */
switch (cmd)
{
@ -1116,7 +1116,8 @@ int mio_dev_watch (mio_dev_t* dev, mio_dev_watch_cmd_t cmd, int events)
if (mio_sys_ctrlmux(mio, mux_cmd, dev, dev_cap) <= -1) return -1;
}
dev->dev_cap = dev_cap;
/* UGLY. MIO_DEV_CAP_WATCH_SUSPENDED may be set/unset by mio_sys_ctrlmux. I need this to reflect it */
dev->dev_cap = dev_cap | (dev->dev_cap & MIO_DEV_CAP_WATCH_SUSPENDED);
return 0;
}

View File

@ -390,7 +390,8 @@ enum mio_dev_cap_t
MIO_DEV_CAP_HALTED = (1 << 16),
MIO_DEV_CAP_ZOMBIE = (1 << 17),
MIO_DEV_CAP_RENEW_REQUIRED = (1 << 18),
MIO_DEV_CAP_WATCH_STARTED = (1 << 19)
MIO_DEV_CAP_WATCH_STARTED = (1 << 19),
MIO_DEV_CAP_WATCH_SUSPENDED = (1 << 20)
};
typedef enum mio_dev_cap_t mio_dev_cap_t;

View File

@ -235,26 +235,85 @@ int mio_sys_ctrlmux (mio_t* mio, mio_sys_mux_cmd_t cmd, mio_dev_t* dev, int dev_
}
#elif defined(USE_EPOLL)
mio_sys_mux_t* mux = &mio->sysdep->mux;
static int epoll_cmd[] = { EPOLL_CTL_ADD, EPOLL_CTL_MOD, EPOLL_CTL_DEL };
struct epoll_event ev;
mio_syshnd_t hnd;
mio_uint32_t events;
int x;
MIO_ASSERT (mio, mio == dev->mio);
hnd = dev->dev_mth->getsyshnd(dev);
ev.data.ptr = dev;
ev.events = EPOLLHUP | EPOLLERR /*| EPOLLET*/;
events = 0;
if (dev_cap & MIO_DEV_CAP_IN_WATCHED)
{
ev.events |= EPOLLIN;
events |= EPOLLIN;
#if defined(EPOLLRDHUP)
ev.events |= EPOLLRDHUP;
events |= EPOLLRDHUP;
#endif
if (dev_cap & MIO_DEV_CAP_PRI_WATCHED) ev.events |= EPOLLPRI;
if (dev_cap & MIO_DEV_CAP_PRI_WATCHED) events |= EPOLLPRI;
}
if (dev_cap & MIO_DEV_CAP_OUT_WATCHED) events |= EPOLLOUT;
ev.events = events | EPOLLHUP | EPOLLERR /*| EPOLLET*/;
ev.data.ptr = dev;
switch (cmd)
{
case MIO_SYS_MUX_CMD_INSERT:
if (MIO_UNLIKELY(dev->dev_cap & MIO_DEV_CAP_WATCH_SUSPENDED))
{
mio_seterrnum (mio, MIO_EEXIST);
return -1;
}
x = epoll_ctl(mux->hnd, EPOLL_CTL_ADD, hnd, &ev);
break;
case MIO_SYS_MUX_CMD_UPDATE:
if (MIO_UNLIKELY(!events))
{
if (dev->dev_cap & MIO_DEV_CAP_WATCH_SUSPENDED)
{
/* no change. keep suspended */
return 0;
}
else
{
x = epoll_ctl(mux->hnd, EPOLL_CTL_DEL, hnd, &ev);
if (x >= 0) dev->dev_cap |= MIO_DEV_CAP_WATCH_SUSPENDED;
}
}
else
{
if (dev->dev_cap & MIO_DEV_CAP_WATCH_SUSPENDED)
{
x = epoll_ctl(mux->hnd, EPOLL_CTL_ADD, hnd, &ev);
if (x >= 0) dev->dev_cap &= ~MIO_DEV_CAP_WATCH_SUSPENDED;
}
else
{
x = epoll_ctl(mux->hnd, EPOLL_CTL_MOD, hnd, &ev);
}
}
break;
case MIO_SYS_MUX_CMD_DELETE:
if (dev->dev_cap & MIO_DEV_CAP_WATCH_SUSPENDED)
{
/* clear the SUSPENDED bit because it's a normal deletion */
dev->dev_cap &= ~MIO_DEV_CAP_WATCH_SUSPENDED;
return 0;
}
x = epoll_ctl(mux->hnd, EPOLL_CTL_DEL, hnd, &ev);
break;
default:
mio_seterrnum (mio, MIO_EINVAL);
return -1;
}
if (dev_cap & MIO_DEV_CAP_OUT_WATCHED) ev.events |= EPOLLOUT;
if (epoll_ctl(mux->hnd, epoll_cmd[cmd], dev->dev_mth->getsyshnd(dev), &ev) == -1)
if (x == -1)
{
mio_seterrwithsyserr (mio, 0, errno);
return -1;

View File

@ -68,7 +68,7 @@ struct mio_sys_mux_t
struct mio_sys_mux_t
{
int hnd;
struct epoll_event revs[100]; /* TODO: is it a good size? */
struct epoll_event revs[128]; /* TODO: is it a good size? */
};
#endif