mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 13:58:34 +00:00
util: epoll: add processing of EPOLL{RD}HUP
Currently when we poll a file descriptor, we only process EPOLLIN events and if a connection is closed the receiving side has no means to deal with it. Add a callback for EPOLL{RD}HUP events and the default implementation for these events that removes the file descriptor from epoll and closes it. Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com> Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
parent
584123e99b
commit
c6cb9d882a
@ -333,6 +333,14 @@ struct epoll_rfd {
|
||||
* negative error code
|
||||
*/
|
||||
int (*read_event)(struct epoll_rfd *);
|
||||
|
||||
/*
|
||||
* EPOLLHUP | EPOLLRDHUP notification. The remote side has
|
||||
* close the connection for rfd->fd.
|
||||
* @return 0 to resume polling, 1 to stop polling or a
|
||||
* negative error code
|
||||
*/
|
||||
int (*hangup_event)(struct epoll_rfd *);
|
||||
};
|
||||
|
||||
extern int epoll_add_rfd(int epfd, struct epoll_rfd *);
|
||||
|
43
criu/util.c
43
criu/util.c
@ -1324,7 +1324,7 @@ int epoll_add_rfd(int epfd, struct epoll_rfd *rfd)
|
||||
{
|
||||
struct epoll_event ev;
|
||||
|
||||
ev.events = EPOLLIN;
|
||||
ev.events = EPOLLIN | EPOLLRDHUP;
|
||||
ev.data.ptr = rfd;
|
||||
if (epoll_ctl(epfd, EPOLL_CTL_ADD, rfd->fd, &ev) == -1) {
|
||||
pr_perror("epoll_ctl failed");
|
||||
@ -1344,6 +1344,24 @@ int epoll_del_rfd(int epfd, struct epoll_rfd *rfd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int epoll_hangup_event(int epollfd, struct epoll_rfd *rfd)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (rfd->hangup_event) {
|
||||
ret = rfd->hangup_event(rfd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (epoll_del_rfd(epollfd, rfd))
|
||||
return -1;
|
||||
|
||||
close_safe(&rfd->fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int epoll_run_rfds(int epollfd, struct epoll_event *evs, int nr_fds, int timeout)
|
||||
{
|
||||
int ret, i, nr_events;
|
||||
@ -1360,13 +1378,26 @@ int epoll_run_rfds(int epollfd, struct epoll_event *evs, int nr_fds, int timeout
|
||||
nr_events = ret;
|
||||
for (i = 0; i < nr_events; i++) {
|
||||
struct epoll_rfd *rfd;
|
||||
uint32_t events;
|
||||
|
||||
rfd = (struct epoll_rfd *)evs[i].data.ptr;
|
||||
ret = rfd->read_event(rfd);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (ret > 0)
|
||||
have_a_break = true;
|
||||
events = evs[i].events;
|
||||
|
||||
if (events & EPOLLIN) {
|
||||
ret = rfd->read_event(rfd);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (ret > 0)
|
||||
have_a_break = true;
|
||||
}
|
||||
|
||||
if (events & (EPOLLHUP | EPOLLRDHUP)) {
|
||||
ret = epoll_hangup_event(epollfd, rfd);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (ret > 0)
|
||||
have_a_break = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (have_a_break)
|
||||
|
Loading…
x
Reference in New Issue
Block a user