Hash :
b1b69ac7
        
        Author :
  
        
        Date :
2014-01-17T23:20:42
        
      
Implemented EV_CLOSED event for epoll backend (EPOLLRDHUP).
- Added new EV_CLOSED event - detects premature connection close
  by clients without the necessity of reading all the pending
  data. Does not depend on EV_READ and/or EV_WRITE.
- Added new EV_FEATURE_EARLY_CLOSED feature for epoll.
  Must be supported for listening to EV_CLOSED event.
- Added new regression test: test-closed.c
- All regression tests passed (test/regress and test/test.sh)
- strace output of test-closed using EV_CLOSED:
    socketpair(PF_LOCAL, SOCK_STREAM, 0, [6, 7]) = 0
    sendto(6, "test string\0", 12, 0, NULL, 0) = 12
    shutdown(6, SHUT_WR)                    = 0
    epoll_ctl(3, EPOLL_CTL_ADD, 7, {EPOLLRDHUP, {u32=7, u64=7}}) = 0
    epoll_wait(3, {{EPOLLRDHUP, {u32=7, u64=7}}}, 32, 3000) = 1
    epoll_ctl(3, EPOLL_CTL_MOD, 7, {EPOLLRDHUP, {u32=7, u64=7}}) = 0
    fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 4), ...})
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYM...
    write(1, "closed_cb: detected connection close "..., 45) = 45
      
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
#!/usr/bin/python2
def get(old,wc,rc,cc):
    if ('xxx' in (rc, wc, cc)):
        return "0",255
    if ('add' in (rc, wc, cc)):
        events = []
        if rc == 'add' or (rc != 'del' and 'r' in old):
            events.append("EPOLLIN")
        if wc == 'add' or (wc != 'del' and 'w' in old):
            events.append("EPOLLOUT")
        if cc == 'add' or (cc != 'del' and 'c' in old):
            events.append("EPOLLRDHUP")
        if old == "0":
            op = "EPOLL_CTL_ADD"
        else:
            op = "EPOLL_CTL_MOD"
        return "|".join(events), op
    if ('del' in (rc, wc, cc)):
        delevents = []
        modevents = []
        op = "EPOLL_CTL_DEL"
        if 'r' in old:
            modevents.append("EPOLLIN")
        if 'w' in old:
            modevents.append("EPOLLOUT")
        if 'c' in old:
            modevents.append("EPOLLRDHUP")
        for item, event in [(rc,"EPOLLIN"),
                            (wc,"EPOLLOUT"),
                            (cc,"EPOLLRDHUP")]:
            if item == 'del':
                delevents.append(event)
                if event in modevents:
                    modevents.remove(event)
        if modevents:
            return "|".join(modevents), "EPOLL_CTL_MOD"
        else:
            return "|".join(delevents), "EPOLL_CTL_DEL"
    return 0, 0
def fmt(op, ev, old, wc, rc, cc):
    entry = "{ %s, %s },"%(op, ev)
    print "\t/* old=%3s, write:%3s, read:%3s, close:%3s */\n\t%s" % (
        old, wc, rc, cc, entry)
    return len(entry)
for old in ('0','r','w','rw','c','cr','cw','crw'):
    for wc in ('0', 'add', 'del', 'xxx'):
        for rc in ('0', 'add', 'del', 'xxx'):
            for cc in ('0', 'add', 'del', 'xxx'):
                op,ev = get(old,wc,rc,cc)
                fmt(op, ev, old, wc, rc, cc)