diff options
| author | Zhang Huan <zhanghuan@open-fs.com> | 2019-01-08 16:17:06 +0800 | 
|---|---|---|
| committer | Amar Tumballi <amarts@redhat.com> | 2019-01-28 04:52:37 +0000 | 
| commit | f747d55a7fd364e2b9a74fe40360ab3cb7b11537 (patch) | |
| tree | 70ccd73edaa2b2e00ba2f3c8006d8624c9875e8d /libglusterfs | |
| parent | 72922c1fd69191b220f79905a23395c3a87f86ce (diff) | |
socket: fix issue on concurrent handle of a socket
Found an issue on concurrent invoke of event handler to the same socket
fd, causing memory corruption. This issue arises after applying commit
"socket: Remove redundant in_lock in incoming message handling" that
removes priv->in_lock to serialize socket read.
The following call sequence describes how concurrent socket event handle
happens.
   thread 1                    thread 2                thread 3
epoll_wait() return
(slot->in_handler is 0)  call select_on_epoll()
                         and epoll_ctl() on fd
                                                    epoll_wait() return
slot->in_handler++
(slot->in_handler is 1)
                                                    slot->in_handler++
                                                    (slot->in_handler is 2)
call handler()                                      call handler()
Fix this issue by skip invoke of handler if there is already a handler
inprogress.
Change-Id: I437126ac772debcadb00993a948919c931cd607b
updates: bz#1467614
Signed-off-by: Zhang Huan <zhanghuan@open-fs.com>
Diffstat (limited to 'libglusterfs')
| -rw-r--r-- | libglusterfs/src/event-epoll.c | 6 | 
1 files changed, 6 insertions, 0 deletions
diff --git a/libglusterfs/src/event-epoll.c b/libglusterfs/src/event-epoll.c index 38acdadbe00..dcaf9804529 100644 --- a/libglusterfs/src/event-epoll.c +++ b/libglusterfs/src/event-epoll.c @@ -623,6 +623,12 @@ event_dispatch_epoll_handler(struct event_pool *event_pool,          handler = slot->handler;          data = slot->data; +        if (slot->in_handler > 0) { +            /* Another handler is inprogress, skip this one. */ +            handler = NULL; +            goto pre_unlock; +        } +          if (slot->handled_error) {              handled_error_previously = _gf_true;          } else {  | 
