Asyncio was disabling and enabling SIGPIPE for each send. At least on Linux
(and probably BSD), we can use MSG_NOSIGNAL in most cases. Attached is
a patch
that implements this. Not specifically benchmarked, but it's always
good to get rid of
extra system calls...
Thanks,
Ben
--
Ben Greear <[EMAIL PROTECTED]>
Candela Technologies Inc http://www.candelatech.com
Index: asyncio.cc
===================================================================
RCS file: /cvs/xorp/libxorp/asyncio.cc,v
retrieving revision 1.40
diff -u -r1.40 asyncio.cc
--- asyncio.cc 4 Jan 2008 03:16:32 -0000 1.40
+++ asyncio.cc 20 Mar 2008 07:23:56 -0000
@@ -205,8 +205,12 @@
_last_error = 0;
done = ::read(_fd, head->buffer() + head->offset(),
head->buffer_bytes() - head->offset());
- if (done < 0)
+ if (done < 0) {
_last_error = errno;
+ XLOG_WARNING("read error: _fd: %i offset: %i total-len: %i error: %s\n",
+ (int)(_fd), head->offset(), head->buffer_bytes(),
+ strerror(errno));
+ }
errno = 0;
#endif // ! HOST_OS_WINDOWS
@@ -571,8 +575,10 @@
XLOG_ASSERT(! dst_addr.is_zero());
#ifndef HOST_OS_WINDOWS
+#ifndef MSG_NOSIGNAL // save two system calls if MSG_NOSIGNAL is supported.
sig_t saved_sigpipe = signal(SIGPIPE, SIG_IGN);
#endif
+#endif
switch (dst_addr.af()) {
case AF_INET:
@@ -584,7 +590,11 @@
done = ::sendto(_fd, XORP_CONST_BUF_CAST(_iov[0].iov_base),
_iov[0].iov_len,
+#ifdef MSG_NOSIGNAL
+ MSG_NOSIGNAL,
+#else
0,
+#endif
reinterpret_cast<const sockaddr*>(&sin),
sizeof(sin));
break;
@@ -599,7 +609,11 @@
done = ::sendto(_fd, XORP_CONST_BUF_CAST(_iov[0].iov_base),
_iov[0].iov_len,
+#ifdef MSG_NOSIGNAL
+ MSG_NOSIGNAL,
+#else
0,
+#endif
reinterpret_cast<const sockaddr*>(&sin6),
sizeof(sin6));
break;
@@ -620,8 +634,10 @@
}
#ifndef HOST_OS_WINDOWS
+#ifndef MSG_NOSIGNAL
signal(SIGPIPE, saved_sigpipe);
#endif
+#endif
} else {
//
@@ -654,16 +670,34 @@
_last_error = (result == FALSE) ? GetLastError() : 0;
}
#else // ! HOST_OS_WINDOWS
- sig_t saved_sigpipe = signal(SIGPIPE, SIG_IGN);
- errno = 0;
- _last_error = 0;
- done = ::writev(_fd, _iov, (int)iov_cnt);
- if (done < 0)
- _last_error = errno;
- errno = 0;
+#ifdef MSG_NOSIGNAL
+ if (iov_cnt == 1) {
+ // No need for coelesce, so use send. This saves us the two
+ // sigaction calls since we can pass the MSG_NOSIGNAL flag.
+ errno = 0;
+ _last_error = 0;
+ done = ::send(_fd, XORP_CONST_BUF_CAST(_iov[0].iov_base),
+ _iov[0].iov_len, MSG_NOSIGNAL);
+ if (done < 0)
+ _last_error = errno;
+ errno = 0;
+ }
+ else {
+#endif
+ sig_t saved_sigpipe = signal(SIGPIPE, SIG_IGN);
- signal(SIGPIPE, saved_sigpipe);
+ errno = 0;
+ _last_error = 0;
+ done = ::writev(_fd, _iov, (int)iov_cnt);
+ if (done < 0)
+ _last_error = errno;
+ errno = 0;
+
+ signal(SIGPIPE, saved_sigpipe);
+#ifdef HOST_OS_LINUX
+ }
+#endif
#endif // ! HOST_OS_WINDOWS
}
_______________________________________________
Xorp-hackers mailing list
[email protected]
http://mailman.ICSI.Berkeley.EDU/mailman/listinfo/xorp-hackers