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