diff --git a/gio/gunixfdmessage.c b/gio/gunixfdmessage.c index aaf749beb..21e52e3c1 100644 --- a/gio/gunixfdmessage.c +++ b/gio/gunixfdmessage.c @@ -318,5 +318,5 @@ g_unix_fd_message_append_fd (GUnixFDMessage *message, { g_return_val_if_fail (G_UNIX_FD_MESSAGE (message), FALSE); - return g_unix_fd_list_append (message->priv->list, fd, error) > 0; + return g_unix_fd_list_append (message->priv->list, fd, error) >= 0; } diff --git a/gio/tests/socket.c b/gio/tests/socket.c index 9c4c0d684..00e959839 100644 --- a/gio/tests/socket.c +++ b/gio/tests/socket.c @@ -23,8 +23,12 @@ #include #ifdef G_OS_UNIX +#include #include #include +#include +#include +#include #include #endif @@ -67,6 +71,106 @@ test_unix_connection (void) g_object_unref (c); g_object_unref (s); } + +static GSocketConnection * +create_connection_for_fd (int fd) +{ + GError *err = NULL; + GSocket *socket; + GSocketConnection *connection; + + socket = g_socket_new_from_fd (fd, &err); + g_assert_no_error (err); + g_assert (G_IS_SOCKET (socket)); + connection = g_socket_connection_factory_create_connection (socket); + g_assert (G_IS_UNIX_CONNECTION (connection)); + g_object_unref (socket); + return connection; +} + +#define TEST_DATA "failure to say failure to say 'i love gnome-panel!'." + +static void +test_unix_connection_ancillary_data (void) +{ + GError *err = NULL; + gint pv[2], sv[3]; + gint status, fd, len; + char buffer[1024]; + pid_t pid; + + status = pipe (pv); + g_assert_cmpint (status, ==, 0); + + status = socketpair (PF_UNIX, SOCK_STREAM, 0, sv); + g_assert_cmpint (status, ==, 0); + + pid = fork (); + g_assert_cmpint (pid, >=, 0); + + /* Child: close its copy of the write end of the pipe, receive it + * again from the parent over the socket, and write some text to it. + * + * Parent: send the write end of the pipe (still open for the + * parent) over the socket, close it, and read some text from the + * read end of the pipe. + */ + if (pid == 0) + { + GSocketConnection *connection; + + close (sv[1]); + connection = create_connection_for_fd (sv[0]); + + status = close (pv[1]); + g_assert_cmpint (status, ==, 0); + + err = NULL; + fd = g_unix_connection_receive_fd (G_UNIX_CONNECTION (connection), NULL, + &err); + g_assert_no_error (err); + g_assert_cmpint (fd, >, -1); + g_object_unref (connection); + + do + len = write (fd, TEST_DATA, sizeof (TEST_DATA)); + while (len == -1 && errno == EINTR); + g_assert_cmpint (len, ==, sizeof (TEST_DATA)); + exit (0); + } + else + { + GSocketConnection *connection; + + close (sv[0]); + connection = create_connection_for_fd (sv[1]); + + err = NULL; + g_unix_connection_send_fd (G_UNIX_CONNECTION (connection), pv[1], NULL, + &err); + g_assert_no_error (err); + g_object_unref (connection); + + status = close (pv[1]); + g_assert_cmpint (status, ==, 0); + + memset (buffer, 0xff, sizeof buffer); + do + len = read (pv[0], buffer, sizeof buffer); + while (len == -1 && errno == EINTR); + + g_assert_cmpint (len, ==, sizeof (TEST_DATA)); + g_assert_cmpstr (buffer, ==, TEST_DATA); + + waitpid (pid, &status, 0); + g_assert (WIFEXITED (status)); + g_assert_cmpint (WEXITSTATUS (status), ==, 0); + } + + /* TODO: add test for g_unix_connection_send_credentials() and + * g_unix_connection_receive_credentials(). + */ +} #endif /* G_OS_UNIX */ int @@ -79,6 +183,7 @@ main (int argc, #ifdef G_OS_UNIX g_test_add_func ("/socket/unix-from-fd", test_unix_from_fd); g_test_add_func ("/socket/unix-connection", test_unix_connection); + g_test_add_func ("/socket/unix-connection-ancillary-data", test_unix_connection_ancillary_data); #endif return g_test_run();