Linux epoll return EEXIST on case when op is EPOLL_CTL_ADD, and the supplied

file descriptor fd is already registered with this epoll instance.

MFC after:	1 month
This commit is contained in:
Dmitry Chagin 2017-02-28 19:55:16 +00:00
parent 8bc4edfd75
commit 0633df29be

View File

@ -481,15 +481,34 @@ linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args)
ciargs.changelist = kev;
if (args->op != LINUX_EPOLL_CTL_DEL) {
kev_flags = EV_ADD | EV_ENABLE;
error = epoll_to_kevent(td, epfp, args->fd, &le,
&kev_flags, kev, &nchanges);
if (error != 0)
goto leave0;
}
switch (args->op) {
case LINUX_EPOLL_CTL_MOD:
error = epoll_delete_all_events(td, epfp, args->fd);
if (error != 0)
goto leave0;
/* FALLTHROUGH */
break;
case LINUX_EPOLL_CTL_ADD:
kev_flags = EV_ADD | EV_ENABLE;
/*
* kqueue_register() return ENOENT if event does not exists
* and the EV_ADD flag is not set.
*/
kev[0].flags &= ~EV_ADD;
error = kqfd_register(args->epfd, &kev[0], td, 1);
if (error != ENOENT) {
error = EEXIST;
goto leave0;
}
error = 0;
kev[0].flags |= EV_ADD;
break;
case LINUX_EPOLL_CTL_DEL:
@ -502,11 +521,6 @@ linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args)
goto leave0;
}
error = epoll_to_kevent(td, epfp, args->fd, &le, &kev_flags,
kev, &nchanges);
if (error != 0)
goto leave0;
epoll_fd_install(td, args->fd, le.data);
error = kern_kevent_fp(td, epfp, nchanges, 0, &k_ops, NULL);