jsdb on linux should not use select()

31 views
Skip to first unread message

gilado

unread,
Sep 19, 2015, 6:49:21 AM9/19/15
to JSDB
select() does not work correctly (and may crash) if the process has more than 1024 file descriptors and a socket given to select uses a file descriptor >= 1024.

Usually that is not a problem because the default limit of fd's per process is 1024. However, if your server has a higher limit and your program opens many files and/or sockets (more than 1024) jsdb streams will not function correctly.  jsdb uses select() in a few places, the most problematic is in bool InternetStream::wait(int ms) which is in rs/io_inet.cpp

Also, both poll() and select() are suseptible to spurious notification where the function indicates data can be read but in fact there is no data. In that case bool InternetStream::canread() will hang while trying to read one byte from the socket.  This happens when the remote side sends so call "naked ack". (There might be other causes as well.) The simplest solution is to use recv() to peek into the socket (linux only flags MSG_DONTWAIT|MSG_PEEK)

Below is a patch that reimplements bool InternetStream::wait(int ms) using poll() and recv() check for Linux only. The old function is used for Windows.

Index: jsdb_source_1.8.0.7/rs/io_inet.cpp
===================================================================
24a25,28
> #include <poll.h>
> #ifndef POLLRDHUP
> #define POLLRDHUP 0x2000
> #endif
515a520,551
> #ifdef XP_UNIX
> bool InternetStream::wait(int ms)
> {
>       struct pollfd fds[1];
>       int rv;
>       char b;
>
>     if (Type == NotOpen)
>         return false;
>        
>     fds[0].fd = s;
>     fds[0].events = POLLIN | POLLRDHUP;
>     fds[0].revents = 0;
>
>     // Use poll since select() breaks when s>=1024
>     rv = poll(fds,1,ms);
>
>     if (rv > 0 && (fds[0].revents & POLLIN)) {
>         // poll(), like select(), has spurious readiness notifications
>         rv = ::recv(s,&b,1,MSG_DONTWAIT | MSG_PEEK);
>         if (rv > 0)
>             return true; // Data is ready
>     }
>
>     if (rv < 0 || (fds[0].revents & POLLRDHUP))
>         Type = NotOpen; // Hard error or remote end closed
>
>     return false;
> }
> #endif
>
> #ifdef XP_WIN
540a577
> #endif








Reply all
Reply to author
Forward
0 new messages