sysdeps-unix: Use MSG_NOSIGNAL when available
authorLennart Poettering <lennart@poettering.net>
Wed, 22 Apr 2009 00:54:23 +0000 (02:54 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 15 May 2009 18:30:15 +0000 (20:30 +0200)
On Linux send()/sendmsg() know the special flag MSG_NOSIGNAL which if
set makes sure that no SIGPIPE signal is raised when we write to a
socket that has been disconnected.

By using this flag we don't have to play games with SIGPIPE which is
pretty ugly stuff since it touches the global process context.

dbus/dbus-sysdeps-unix.c

index 29d234a..2e12982 100644 (file)
@@ -179,7 +179,24 @@ _dbus_write_socket (int               fd,
                     int               start,
                     int               len)
 {
+#ifdef MSG_NOSIGNAL
+  const char *data;
+  int bytes_written;
+
+  data = _dbus_string_get_const_data_len (buffer, start, len);
+
+ again:
+
+  bytes_written = send (fd, data, len, MSG_NOSIGNAL);
+
+  if (bytes_written < 0 && errno == EINTR)
+    goto again;
+
+  return bytes_written;
+
+#else
   return _dbus_write (fd, buffer, start, len);
+#endif
 }
 
 /**
@@ -255,8 +272,52 @@ _dbus_write_socket_two (int               fd,
                         int               start2,
                         int               len2)
 {
+#ifdef MSG_NOSIGNAL
+  struct iovec vectors[2];
+  const char *data1;
+  const char *data2;
+  int bytes_written;
+  struct msghdr m;
+
+  _dbus_assert (buffer1 != NULL);
+  _dbus_assert (start1 >= 0);
+  _dbus_assert (start2 >= 0);
+  _dbus_assert (len1 >= 0);
+  _dbus_assert (len2 >= 0);
+
+  data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
+
+  if (buffer2 != NULL)
+    data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
+  else
+    {
+      data2 = NULL;
+      start2 = 0;
+      len2 = 0;
+    }
+
+  vectors[0].iov_base = (char*) data1;
+  vectors[0].iov_len = len1;
+  vectors[1].iov_base = (char*) data2;
+  vectors[1].iov_len = len2;
+
+  memset(&m, 0, sizeof(m));
+  m.msg_iov = vectors;
+  m.msg_iovlen = data2 ? 2 : 1;
+
+ again:
+
+  bytes_written = sendmsg (fd, &m, MSG_NOSIGNAL);
+
+  if (bytes_written < 0 && errno == EINTR)
+    goto again;
+
+  return bytes_written;
+
+#else
   return _dbus_write_two (fd, buffer1, start1, len1,
                           buffer2, start2, len2);
+#endif
 }