I am looking at the server code, and don't see where you look for the EPOLLHUP. I see where you check for EPOLLIN, but this is always set when epoll returns an fd with data. I have never used Epoll (I generally use select), and it could well be that it never sets EPOLLHUP. When using select, the only way to detect a socket close is when it reports a read available on the fd, but returns 0 on a read.
As for your comment about perl not being the best tool for the job, well I won't even dignify that with a comment.