diff --git a/src/common/fdset.c b/src/common/fdset.c
index 3b4b75aa73ab770e23eb332e7747cd951fb58cdc..96a6e51be479dafcf92479dfc3f0ff9f960cbc64 100644
--- a/src/common/fdset.c
+++ b/src/common/fdset.c
@@ -62,20 +62,20 @@ static void fdset_set_backend(struct fdset_backend_t *backend) {
 void __attribute__ ((constructor)) fdset_init()
 {
 	/* Preference: epoll */
-#ifdef HAVE_EPOLL_WAIT
-	if (dlsym(RTLD_DEFAULT, "epoll_wait") != 0) {
-		fdset_set_backend(&FDSET_EPOLL);
-		return;
-	}
-#endif
+//#ifdef HAVE_EPOLL_WAIT
+//	if (dlsym(RTLD_DEFAULT, "epoll_wait") != 0) {
+//		fdset_set_backend(&FDSET_EPOLL);
+//		return;
+//	}
+//#endif
 
 	/* Preference: kqueue */
-#ifdef HAVE_KQUEUE
-	if (dlsym(RTLD_DEFAULT, "kqueue") != 0) {
-		fdset_set_backend(&FDSET_KQUEUE);
-		return;
-	}
-#endif
+//#ifdef HAVE_KQUEUE
+//	if (dlsym(RTLD_DEFAULT, "kqueue") != 0) {
+//		fdset_set_backend(&FDSET_KQUEUE);
+//		return;
+//	}
+//#endif
 
 	/* Fallback: poll */
 #ifdef HAVE_POLL
diff --git a/src/common/fdset.h b/src/common/fdset.h
index e1facdb06e2ef64fb1fdd3fe68d94ac8e6bbbd77..0edc50b337a06a4058094bc3c9de8b41bea6b1fc 100644
--- a/src/common/fdset.h
+++ b/src/common/fdset.h
@@ -92,6 +92,7 @@ struct fdset_backend_t
 	int (*fdset_destroy)(fdset_t*);
 	int (*fdset_add)(fdset_t*, int, int);
 	int (*fdset_remove)(fdset_t*, int);
+	int (*fdset_set_events)(fdset_t*, int, int);
 	int (*fdset_wait)(fdset_t*, int);
 	int (*fdset_begin)(fdset_t*, fdset_it_t*);
 	int (*fdset_end)(fdset_t*, fdset_it_t*);
@@ -149,6 +150,19 @@ static inline int fdset_add(fdset_t *fdset, int fd, int events) {
  */
 int fdset_remove(fdset_t *fdset, int fd);
 
+/*!
+ * \brief Change descriptor watched events mask.
+ *
+ * \param fdset Target set.
+ * \param fd Related file descriptor.
+ *
+ * \retval 0 if successful.
+ * \retval -1 if not found.
+ */
+static inline int fdset_set_events(fdset_t *fdset, int fd, int events) {
+	return _fdset_backend.fdset_set_events(fdset, fd, events);
+}
+
 /*!
  * \brief Poll set for new events.
  *
diff --git a/src/common/fdset_epoll.c b/src/common/fdset_epoll.c
index f889dd33c557430fb884966e891f56125ecb086f..993a432fc2de6dd3727ea7d967d4a41fefc97301 100644
--- a/src/common/fdset_epoll.c
+++ b/src/common/fdset_epoll.c
@@ -81,8 +81,13 @@ int fdset_epoll_add(fdset_t *fdset, int fd, int events)
 	/* Add to epoll set. */
 	struct epoll_event ev;
 	memset(&ev, 0, sizeof(struct epoll_event));
-	ev.events = EPOLLIN;
 	ev.data.fd = fd;
+	/* Build mask. */
+	ev.events = 0;
+	if (events & OS_EV_READ)
+		ev.events = EPOLLIN;
+	if (events & OS_EV_WRITE)
+		ev.events = EPOLLOUT;
 	if (epoll_ctl(fdset->epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
 		return -1;
 	}
@@ -114,6 +119,27 @@ int fdset_epoll_remove(fdset_t *fdset, int fd)
 	return 0;
 }
 
+int fdset_epoll_set_events(fdset_t *fdset, int fd, int events)
+{
+	/* Add to epoll set. */
+	struct epoll_event ev;
+	memset(&ev, 0, sizeof(struct epoll_event));
+	ev.data.fd = fd;
+
+	/* Build mask. */
+	ev.events = 0;
+	if (events & OS_EV_READ)
+		ev.events = EPOLLIN;
+	if (events & OS_EV_WRITE)
+		ev.events = EPOLLOUT;
+
+	if (epoll_ctl(fdset->epfd, EPOLL_CTL_MOD, fd, &ev) < 0) {
+		return -1;
+	}
+	return 0;
+}
+
+
 int fdset_epoll_wait(fdset_t *fdset, int timeout)
 {
 	if (fdset == NULL || fdset->nfds < 1 || fdset->events == NULL) {
@@ -195,6 +221,7 @@ struct fdset_backend_t FDSET_EPOLL = {
 	.fdset_destroy = fdset_epoll_destroy,
 	.fdset_add = fdset_epoll_add,
 	.fdset_remove = fdset_epoll_remove,
+	.fdset_set_events = fdset_epoll_set_events,
 	.fdset_wait = fdset_epoll_wait,
 	.fdset_begin = fdset_epoll_begin,
 	.fdset_end = fdset_epoll_end,
diff --git a/src/common/fdset_epoll.h b/src/common/fdset_epoll.h
index 58f25f81e7df57c51eadb6dbc52bb7a15b1c070a..a5947378ca7d1eff23f9adc083003198d0095a7b 100644
--- a/src/common/fdset_epoll.h
+++ b/src/common/fdset_epoll.h
@@ -70,6 +70,17 @@ int fdset_epoll_add(fdset_t *fdset, int fd, int events);
  */
 int fdset_epoll_remove(fdset_t *fdset, int fd);
 
+/*!
+ * \brief Change descriptor watched events mask.
+ *
+ * \param fdset Target set.
+ * \param fd Related file descriptor.
+ *
+ * \retval 0 if successful.
+ * \retval -1 if not found.
+ */
+int fdset_epoll_set_events(fdset_t *fdset, int fd, int events);
+
 /*!
  * \brief Poll set for new events.
  *
diff --git a/src/common/fdset_kqueue.c b/src/common/fdset_kqueue.c
index 7c52f71ba96cac4c82ccf5f7104573d2f96b5597..0685f87aef868347977a4f5c55e54274250466a1 100644
--- a/src/common/fdset_kqueue.c
+++ b/src/common/fdset_kqueue.c
@@ -91,10 +91,15 @@ int fdset_kqueue_add(fdset_t *fdset, int fd, int events)
 		return ret;
 	}
 
+	/* Build mask. */
+	int mask = 0;
+	if (events & OS_EV_READ)
+		mask |= EVFILT_READ;
+	if (events & OS_EV_WRITE)
+		mask |= EVFILT_WRITE;
+
 	/* Add to kqueue set. */
-	int evfilt = EVFILT_READ;
-	EV_SET(&fdset->events[fdset->nfds], fd, evfilt,
-	       EV_ADD|EV_ENABLE, 0, 0, 0);
+	EV_SET(&fdset->events[fdset->nfds], fd, mask, EV_ADD|EV_ENABLE, 0, 0, 0);
 	memset(fdset->revents + fdset->nfds, 0, sizeof(struct kevent));
 
 	++fdset->nfds;
@@ -154,6 +159,27 @@ int fdset_kqueue_remove(fdset_t *fdset, int fd)
 	return 0;
 }
 
+int fdset_kqueue_set_events(fdset_t *fdset, int fd, int events)
+{
+	/* Build mask. */
+	int mask = 0;
+	if (events & OS_EV_READ)
+		mask |= EVFILT_READ;
+	if (events & OS_EV_WRITE)
+		mask |= EVFILT_WRITE;
+
+	/* Find in set. */
+	struct kevent *evs = fdset->events;
+	for (int i = 0; i < fdset->nfds; ++i) {
+		if (evs[i].ident == fd) {
+			EV_SET(evs + i, fd, mask, EV_ADD|EV_ENABLE, 0, 0, 0);
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
 int fdset_kqueue_wait(fdset_t *fdset, int timeout)
 {
 	if (fdset == NULL || fdset->nfds < 1 || fdset->events == NULL) {
@@ -250,6 +276,7 @@ struct fdset_backend_t FDSET_KQUEUE = {
 	.fdset_destroy = fdset_kqueue_destroy,
 	.fdset_add = fdset_kqueue_add,
 	.fdset_remove = fdset_kqueue_remove,
+	.fdset_set_events = fdset_kqueue_set_events,
 	.fdset_wait = fdset_kqueue_wait,
 	.fdset_begin = fdset_kqueue_begin,
 	.fdset_end = fdset_kqueue_end,
diff --git a/src/common/fdset_kqueue.h b/src/common/fdset_kqueue.h
index 4b650a7b90a26389c162e200038884c5bc3d0d0c..3d6d118c4284d109d49940fd5d4b09df39d69b45 100644
--- a/src/common/fdset_kqueue.h
+++ b/src/common/fdset_kqueue.h
@@ -70,6 +70,17 @@ int fdset_kqueue_add(fdset_t *fdset, int fd, int events);
  */
 int fdset_kqueue_remove(fdset_t *fdset, int fd);
 
+/*!
+ * \brief Change descriptor watched events mask.
+ *
+ * \param fdset Target set.
+ * \param fd Related file descriptor.
+ *
+ * \retval 0 if successful.
+ * \retval -1 if not found.
+ */
+int fdset_kqueue_set_events(fdset_t *fdset, int fd, int events);
+
 /*!
  * \brief Poll set for new events.
  *
diff --git a/src/common/fdset_poll.c b/src/common/fdset_poll.c
index e16ae11e0bfd8ced9eef2b26bec7df8539324767..d2ea86a15f39fdded85757729907e83fc0277448 100644
--- a/src/common/fdset_poll.c
+++ b/src/common/fdset_poll.c
@@ -73,8 +73,15 @@ int fdset_poll_add(fdset_t *fdset, int fd, int events)
 	/* Append. */
 	int nid = fdset->nfds++;
 	fdset->fds[nid].fd = fd;
-	fdset->fds[nid].events = POLLIN;
 	fdset->fds[nid].revents = 0;
+
+	/* Build mask. */
+	fdset->fds[nid].events = 0;
+	if (events & OS_EV_READ)
+		fdset->fds[nid].events |= POLLIN;
+	if (events & OS_EV_WRITE)
+		fdset->fds[nid].events |= POLLOUT;
+
 	return 0;
 }
 
@@ -112,6 +119,23 @@ int fdset_poll_remove(fdset_t *fdset, int fd)
 	return 0;
 }
 
+int fdset_poll_set_events(fdset_t *fdset, int fd, int events)
+{
+	struct pollfd *pfd = fdset->fds;
+	for (size_t i = 0; i < fdset->nfds; ++i) {
+		if (pfd[i].fd == fd) {
+			pfd[i].events = 0;
+			if (events & OS_EV_READ)
+				pfd[i].events |= POLLIN;
+			if (events & OS_EV_WRITE)
+				pfd[i].events |= POLLOUT;
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
 int fdset_poll_wait(fdset_t *fdset, int timeout)
 {
 	if (fdset == NULL || fdset->nfds < 1 || fdset->fds == NULL) {
@@ -125,7 +149,7 @@ int fdset_poll_wait(fdset_t *fdset, int timeout)
 	/* Poll for events. */
 	int ret = poll(fdset->fds, fdset->nfds, timeout);
 	if (ret < 0) {
-		return -1;
+		return ret;
 	}
 
 	/* Set pointers for iterating. */
@@ -161,7 +185,7 @@ int fdset_poll_end(fdset_t *fdset, fdset_it_t *it)
 	/* Trace last matching item from the end. */
 	struct pollfd* pfd = fdset->fds + fdset->nfds - 1;
 	while (pfd != fdset->fds) {
-		if (pfd->events & pfd->revents) {
+		if (pfd->revents != 0) {
 			it->fd = pfd->fd;
 			it->pos = pfd - fdset->fds;
 			return 0;
@@ -183,7 +207,7 @@ int fdset_poll_next(fdset_t *fdset, fdset_it_t *it)
 	/* Find next with matching flags. */
 	for (; it->pos < fdset->nfds; ++it->pos) {
 		struct pollfd* pfd = fdset->fds + it->pos;
-		if (pfd->events & pfd->revents) {
+		if (pfd->revents != 0) {
 			it->fd = pfd->fd;
 			it->events = pfd->revents;
 			++it->pos; /* Next will start after current. */
@@ -208,6 +232,7 @@ struct fdset_backend_t FDSET_POLL = {
 	.fdset_destroy = fdset_poll_destroy,
 	.fdset_add = fdset_poll_add,
 	.fdset_remove = fdset_poll_remove,
+	.fdset_set_events = fdset_poll_set_events,
 	.fdset_wait = fdset_poll_wait,
 	.fdset_begin = fdset_poll_begin,
 	.fdset_end = fdset_poll_end,
diff --git a/src/common/fdset_poll.h b/src/common/fdset_poll.h
index 68e9e69097f339b1d0e8ce8e591f8b288d31cf68..4adc4867000e21084e050482daee1102a34d3ef2 100644
--- a/src/common/fdset_poll.h
+++ b/src/common/fdset_poll.h
@@ -70,6 +70,17 @@ int fdset_poll_add(fdset_t *fdset, int fd, int events);
  */
 int fdset_poll_remove(fdset_t *fdset, int fd);
 
+/*!
+ * \brief Change descriptor watched events mask.
+ *
+ * \param fdset Target set.
+ * \param fd Related file descriptor.
+ *
+ * \retval 0 if successful.
+ * \retval -1 if not found.
+ */
+int fdset_poll_set_events(fdset_t *fdset, int fd, int events);
+
 /*!
  * \brief Poll set for new events.
  *