On Sep 11, 2013, at 12:19 AM, yun...@apache.org wrote:

> Updated Branches:
>  refs/heads/master 40212d2d1 -> 9a6fc2ab6
> 
> 
> TS-2187: use nonblock eventfd in EventNotify
> 
> 1) Use nonblock eventfd, so that we can tolerate write() failed with
>   errno EAGANIN – which is acceptable as the signal receiver will be
>   notified eventually in this case.
> 
> 2) After using nonblock eventfd, read() will not block in wait(). So
>   I use epoll_wait() to implement block behavior, just like timedwait().
> 
> 3) nonblock eventfd can fix a potential problem: if receiver didn't
>   read() data immediately, senders might block in write().
> 
> Signed-off-by: Yunkai Zhang <qiushu....@taobao.com>
> 
> 
> Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
> Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/9a6fc2ab
> Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/9a6fc2ab
> Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/9a6fc2ab
> 
> Branch: refs/heads/master
> Commit: 9a6fc2ab6b3147e82dfc229a7158083371d5545e
> Parents: 40212d2
> Author: Yunkai Zhang <qiushu....@taobao.com>
> Authored: Sun Sep 8 23:35:39 2013 +0800
> Committer: Yunkai Zhang <qiushu....@taobao.com>
> Committed: Wed Sep 11 15:18:18 2013 +0800
> 
> ----------------------------------------------------------------------
> CHANGES               |  2 ++
> lib/ts/EventNotify.cc | 42 +++++++++++++++++++++++++++++++-----------
> lib/ts/EventNotify.h  |  2 +-
> 3 files changed, 34 insertions(+), 12 deletions(-)
> ----------------------------------------------------------------------
> 
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/9a6fc2ab/CHANGES
> ----------------------------------------------------------------------
> diff --git a/CHANGES b/CHANGES
> index d042183..adeb534 100644
> --- a/CHANGES
> +++ b/CHANGES
> @@ -1,6 +1,8 @@
>                                                          -*- coding: utf-8 -*-
> Changes with Apache Traffic Server 4.1.0
> 
> +  *) [TS-2187] failed assert `nr == sizeof(uint64_t)` in 
> EventNotify::signal()
> +
>   *) [TS-2206] The trafficserver RC script does not use absolute path to
>    traffic_line binary.
> 
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/9a6fc2ab/lib/ts/EventNotify.cc
> ----------------------------------------------------------------------
> diff --git a/lib/ts/EventNotify.cc b/lib/ts/EventNotify.cc
> index 3a499b6..feb9ad8 100644
> --- a/lib/ts/EventNotify.cc
> +++ b/lib/ts/EventNotify.cc
> @@ -32,6 +32,7 @@
> 
> #ifdef HAVE_EVENTFD
> #include <sys/eventfd.h>
> +#include <sys/fcntl.h>
> #include <sys/epoll.h>
> #endif
> 
> @@ -41,11 +42,13 @@ EventNotify::EventNotify()
>   int ret;
>   struct epoll_event ev;
> 
> -  // Don't use noblock here!
> -  m_event_fd = eventfd(0, EFD_CLOEXEC);
> +  m_event_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
>   if (m_event_fd < 0) {

Should be if (m_event_fd == -1 && errno == EINVAL).

> -    // EFD_CLOEXEC invalid in <= Linux 2.6.27
> +    // EFD_NONBLOCK/EFD_CLOEXEC invalid in <= Linux 2.6.27
>     m_event_fd = eventfd(0, 0);
> +
> +    fcntl(m_event_fd, F_SETFD, FD_CLOEXEC);
> +    fcntl(m_event_fd, F_SETFL, O_NONBLOCK);
>   }
>   ink_release_assert(m_event_fd != -1);
> 
> @@ -69,23 +72,39 @@ EventNotify::signal(void)
> #ifdef HAVE_EVENTFD
>   ssize_t nr;
>   uint64_t value = 1;
> +  //
> +  // If the addition would cause the counter’s value of eventfd
> +  // to exceed the maximum, write() will fail with the errno EAGAIN,
> +  // which is acceptable as the receiver will be notified eventually.
> +  //

This would have to be a bug, right?

>   nr = write(m_event_fd, &value, sizeof(uint64_t));
> -  ink_release_assert(nr == sizeof(uint64_t));
> #else
>   ink_cond_signal(&m_cond);
> #endif
> }
> 
> -void
> +int
> EventNotify::wait(void)
> {
> #ifdef HAVE_EVENTFD
> -  ssize_t nr;
> +  ssize_t nr, nr_fd;
>   uint64_t value = 0;
> +  struct epoll_event ev;
> +
> +  do {
> +    nr_fd = epoll_wait(m_epoll_fd, &ev, 1, -1);
> +  } while (nr_fd == -1 && errno == EINTR);
> +
> +  if (nr_fd == -1)
> +    return errno;
> +
>   nr = read(m_event_fd, &value, sizeof(uint64_t));
> -  ink_release_assert(nr == sizeof(uint64_t));
> +  if (nr == sizeof(uint64_t))
> +    return 0;
> +  else
> +    return errno;
> #else
> -  ink_cond_wait(&m_cond, &m_mutex);
> +  return ink_cond_wait(&m_cond, &m_mutex);
> #endif
> }

So with eventfd() support, EventNotify::wait can fail, but otherwise it can't 
fail. It would be better if the API was consistent.

> 
> @@ -115,9 +134,10 @@ EventNotify::timedwait(int timeout) // milliseconds
>     return errno;
> 
>   nr = read(m_event_fd, &value, sizeof(uint64_t));
> -  ink_release_assert(nr == sizeof(uint64_t));
> -
> -  return 0;
> +  if (nr == sizeof(uint64_t))
> +    return 0;
> +  else
> +    return errno;

It might be cleaner to use eventfd_read() and eventfd_write().

> #else
>   ink_timestruc abstime;
>   ink_hrtime curtime;
> 
> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/9a6fc2ab/lib/ts/EventNotify.h
> ----------------------------------------------------------------------
> diff --git a/lib/ts/EventNotify.h b/lib/ts/EventNotify.h
> index b74e3af..7223e6d 100644
> --- a/lib/ts/EventNotify.h
> +++ b/lib/ts/EventNotify.h
> @@ -38,7 +38,7 @@ class EventNotify
> public:
>   EventNotify();
>   void signal(void);
> -  void wait(void);
> +  int wait(void);
>   int timedwait(int timeout); // milliseconds
>   void lock(void);
>   bool trylock(void);
> 

Reply via email to