Quoting Frank Schmirler vdr@schmirler.de:
Hi,
I would like to raise an issue with SVDRP. When the client doesn't send QUIT but simply closes the connection, VDR happily ignores the EOF returned by read. The socket will remain in state CLOSE_WAIT until it's finally closed due to the SVDRP timeout. In the meantime the SVDRP port remains blocked for other clients.
I think the way it was implemented until vdr-1.2.1 was correct. Then a broken pipe problem was reported (http://linvdr.org/mailinglists/vdr/2003/07/msg00254.html) and the implementation of cSVDRP::Process was modified to the way which is still used in 1.4.1.
The way it is implemented now is IMHO broken. So I would suggest to return to the way it was initially implemented or - if someone has an idea where broken pipes might come from - find a better way to fix it. Maybe the broken pipes at that time even had a totally different cause?
Code <= 1.2.1: while (file.Ready(false)) { unsigned char c; int r = safe_read(file, &c, 1); if (r > 0) { ... } else if (r <= 0) { isyslog("lost connection to SVDRP client"); Close(); } }
read() returning 0 means eof. So above code should be the correct one (tm) . But safe_read() has to be modified, as socket is non-blocking (oldflags |= O_NONBLOCK;), EAGAIN should be handled too:
ssize_t safe_read(int filedes, void *buffer, size_t size) { for (;;) { ssize_t p = read(filedes, buffer, size); if (p < 0) { if (errno == EINTR) { dsyslog("EINTR while reading from file handle %d - retrying", filedes); continue; } if (errno == EAGAIN) { dsyslog("EAGAIN while reading from file handle %d - retrying", filedes); usleep (10000); continue; } } return p; } }
Code >= 1.2.4 while (file.Ready(false)) { unsigned char c; int r = safe_read(file, &c, 1); if (r > 0) { ... } else if (r < 0) { isyslog("lost connection to SVDRP client"); Close(); } else break; }
Stefan Lucke