The following patch against HEAD allows one to specify timeouts for the reads and writes performed by afxiopipestream objects. I use this to catch long delays when reading or writing data from an afxiopipestream object bound to a socket file descriptor. The default behavior is the current behavior with "infinite" (actually system-specific) timeouts. The changes to afx.h are source-compatible, so existing code that uses afxiopipestream objects does not need to be changed.

As an aside, the afxiopipestream class is very nice to use. It allows binding a stream to a file descriptor and manages the buffering automatically. The only extra thing I needed was a way to time-out the reads and writes to the file descriptor, which the attached patch provides.

        Cheers,

        -- Johnny C. Lam
diff -ur afx/afx.h /home/jlam/milter/afx/afx.h
--- afx/afx.h   Mon Jul 30 00:25:53 2007
+++ /home/jlam/milter/afx/afx.h Tue Oct 23 22:02:51 2007
@@ -8,6 +8,9 @@
 
 #include       "afx/config.h"
 
+#if    HAVE_SYS_TYPES_H
+#include       <sys/types.h>
+#endif
 #if    HAVE_UNISTD_H
 #include       <unistd.h>
 #endif
@@ -26,12 +29,15 @@
 class afxpipestreambuf : public std::streambuf {
        int fd;
        char buffer[8192];
+       time_t read_timeout;
+       time_t write_timeout;
 
  public:
+       enum timeout_value { TIMEOUT_INF = 0 };
 
        std::ios *iosp;
 
-       afxpipestreambuf(int);
+       afxpipestreambuf(int, time_t = TIMEOUT_INF, time_t = TIMEOUT_INF);
        ~afxpipestreambuf();
        void close();
        void seekg(std::streampos);
@@ -47,7 +53,9 @@
 class afxipipestream : public std::istream {
        afxpipestreambuf fd_;
  public:
-       afxipipestream(int = -1);
+       enum timeout_value { TIMEOUT_INF = afxpipestreambuf::TIMEOUT_INF };
+
+       afxipipestream(int = -1, time_t = TIMEOUT_INF);
        ~afxipipestream();
 
        void close() { fd_.close(); }
@@ -61,7 +69,9 @@
 class afxopipestream: public std::ostream {
        afxpipestreambuf fd_;
  public:
-       afxopipestream(int = -1);
+       enum timeout_value { TIMEOUT_INF = afxpipestreambuf::TIMEOUT_INF };
+
+       afxopipestream(int = -1, time_t = TIMEOUT_INF);
        ~afxopipestream();
        void close() { fd_.close(); }
        void seekg(std::streampos p) { fd_.seekg(p); }
@@ -74,7 +84,9 @@
 class afxiopipestream: public std::iostream {
        afxpipestreambuf fd_;
  public:
-       afxiopipestream(int = -1);
+       enum timeout_value { TIMEOUT_INF = afxpipestreambuf::TIMEOUT_INF };
+
+       afxiopipestream(int = -1, time_t = TIMEOUT_INF, time_t = TIMEOUT_INF);
        ~afxiopipestream();
        void close() { fd_.close(); }
        void seekg(std::streampos p) { fd_.seekg(p); }
diff -ur afx/afxpipe.C /home/jlam/milter/afx/afxpipe.C
--- afx/afxpipe.C       Sun Aug  5 20:00:33 2001
+++ /home/jlam/milter/afx/afxpipe.C     Tue Oct 23 22:06:57 2007
@@ -4,10 +4,68 @@
 */
 
 #include       "afx.h"
+#include       <errno.h>
+#if    HAVE_SYS_TIME_H
+#include       <sys/time.h>
+#endif
+#if    HAVE_SYS_SELECT_H
+#include       <sys/select.h>
+#endif
 
 static const char rcsid[]="$Id: afxpipe.C,v 2.1 2001/08/05 20:00:33 mrsam Exp 
$";
 
-afxpipestreambuf::afxpipestreambuf(int f) : fd(f), iosp(0)
+static int fd_timeout(int fd, time_t timeout, int read)
+{
+       fd_set readfds, writefds;
+
+       FD_ZERO(&readfds);
+       FD_ZERO(&writefds);
+       if (read)
+               FD_SET(fd, &readfds);
+       else
+               FD_SET(fd, &writefds);
+
+       struct timeval tv, *tvp=0;
+
+       if (timeout != afxpipestreambuf::TIMEOUT_INF)
+       {
+               tv.tv_sec=timeout;
+               tv.tv_usec=0;
+               tvp=&tv;
+       }
+
+       for (;;)
+       {
+       int     rv=select(fd+1, &readfds, &writefds, 0, tvp);
+
+               if (rv > 0)
+               {
+                       if (read)
+                       {
+                               if (!FD_ISSET(fd, &readfds))
+                                       return (-1);
+                       }
+                       else
+                       {
+                               if (!FD_ISSET(fd, &writefds))
+                                       return (-1);
+                       }
+                       return (0);
+               }
+               else if (rv == 0)
+                       return (-1);
+               else if (rv < 0)
+               {
+                       if (errno == EINTR)
+                               continue;
+                       else
+                               return (-1);
+               }
+       }
+}
+
+afxpipestreambuf::afxpipestreambuf(int f, time_t rto, time_t wto)
+       : fd(f), read_timeout(rto), write_timeout(wto), iosp(0)
 {
 }
 
@@ -66,6 +124,10 @@
 
        while (p < e)
        {
+               if (write_timeout != TIMEOUT_INF &&
+                   fd_timeout(fd, write_timeout, 0) < 0)
+                       return (-1);
+
                int n=::write(fd, p, e-p);
 
                if (n <= 0 && iosp)
@@ -86,7 +148,9 @@
        int n;
 
        if (fd < 0)
-         return (-1);
+               return (-1);
+       if (read_timeout != TIMEOUT_INF && fd_timeout(fd, read_timeout, 1) < 0)
+               return (-1);
 
        n=read(fd, buffer, sizeof(buffer));
 
@@ -101,7 +165,8 @@
        return (sgetc());
 }
 
-afxipipestream::afxipipestream(int f) : std::istream(&fd_), fd_(f)
+afxipipestream::afxipipestream(int f, time_t rto)
+       : std::istream(&fd_), fd_(f, rto, TIMEOUT_INF)
 {
        fd_.iosp=this;
 }
@@ -110,7 +175,8 @@
 {
 }
 
-afxopipestream::afxopipestream(int f) : std::ostream(&fd_), fd_(f)
+afxopipestream::afxopipestream(int f, time_t wto)
+       : std::ostream(&fd_), fd_(f, TIMEOUT_INF, wto)
 {
        fd_.iosp=this;
 }
@@ -120,7 +186,8 @@
 }
 
 
-afxiopipestream::afxiopipestream(int f) : std::iostream(&fd_), fd_(f)
+afxiopipestream::afxiopipestream(int f, time_t rto, time_t wto)
+       : std::iostream(&fd_), fd_(f, rto, wto)
 {
        fd_.iosp=this;
 }
diff -ur afx/configure.in /home/jlam/milter/afx/configure.in
--- afx/configure.in    Mon Jul 30 00:25:54 2007
+++ /home/jlam/milter/afx/configure.in  Tue Oct 23 20:49:44 2007
@@ -27,7 +27,7 @@
 
 dnl Checks for header files.
 AC_HEADER_STDC
-AC_CHECK_HEADERS(unistd.h strings.h)
+AC_CHECK_HEADERS(sys/time.h sys/select.h unistd.h strings.h)
 
 dnl Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
diff -ur afx/testafxpipe.C /home/jlam/milter/afx/testafxpipe.C
--- afx/testafxpipe.C   Sun Aug  5 20:00:33 2001
+++ /home/jlam/milter/afx/testafxpipe.C Tue Oct 23 20:54:15 2007
@@ -12,8 +12,8 @@
        int fd0=dup(0);
        int fd1=dup(1);
 
-       afxipipestream i(fd0);
-       afxopipestream o(fd1);
+       afxipipestream i(fd0, 10);
+       afxopipestream o(fd1, 10);
 
        int c;
 
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
courier-users mailing list
[email protected]
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/courier-users

Reply via email to