New mechanism to transfer file descriptors from client to server.
diff --git a/server/request.c b/server/request.c
index b80dd33..96bb711 100644
--- a/server/request.c
+++ b/server/request.c
@@ -204,8 +204,6 @@
{
int ret;
- assert (thread->pass_fd == -1);
-
if (debug_level) trace_reply( thread, request );
request->header.error = thread->error;
@@ -221,43 +219,68 @@
}
}
-/* read a message from a client that has something to say */
-void read_request( struct thread *thread )
+/* receive a file descriptor on the process socket */
+int receive_fd( struct process *process )
{
- union generic_request req;
- int ret;
+ struct send_fd data;
+ int fd, ret;
#ifdef HAVE_MSGHDR_ACCRIGHTS
msghdr.msg_accrightslen = sizeof(int);
- msghdr.msg_accrights = (void *)&thread->pass_fd;
+ msghdr.msg_accrights = (void *)&fd;
#else /* HAVE_MSGHDR_ACCRIGHTS */
msghdr.msg_control = &cmsg;
msghdr.msg_controllen = sizeof(cmsg);
cmsg.fd = -1;
#endif /* HAVE_MSGHDR_ACCRIGHTS */
- assert( thread->pass_fd == -1 );
+ myiovec.iov_base = &data;
+ myiovec.iov_len = sizeof(data);
- myiovec.iov_base = &req;
- myiovec.iov_len = sizeof(req);
-
- ret = recvmsg( thread->obj.fd, &msghdr, 0 );
+ ret = recvmsg( process->obj.fd, &msghdr, 0 );
#ifndef HAVE_MSGHDR_ACCRIGHTS
- thread->pass_fd = cmsg.fd;
+ fd = cmsg.fd;
#endif
- if (ret == sizeof(req))
+ if (ret == sizeof(data))
{
- call_req_handler( thread, &req );
- thread->pass_fd = -1;
- return;
+ struct thread *thread = get_thread_from_id( data.tid );
+ if (!thread || thread->process != process)
+ {
+ if (debug_level)
+ fprintf( stderr, "%08x: *fd* %d <- %d bad thread id\n",
+ (unsigned int)data.tid, data.fd, fd );
+ close( fd );
+ }
+ else
+ {
+ if (debug_level)
+ fprintf( stderr, "%08x: *fd* %d <- %d\n",
+ (unsigned int)thread, data.fd, fd );
+ thread_add_inflight_fd( thread, data.fd, fd );
+ }
+ return 0;
}
- if (!ret) /* closed pipe */
- kill_thread( thread, 0 );
+
+ if (!ret)
+ {
+ set_select_events( &process->obj, -1 ); /* stop waiting on it */
+ }
else if (ret > 0)
- fatal_protocol_error( thread, "partial recvmsg %d\n", ret );
- else
- fatal_protocol_perror( thread, "recvmsg" );
+ {
+ fprintf( stderr, "Protocol error: process %p: partial recvmsg %d for fd\n", process, ret );
+ kill_process( process, NULL, 1 );
+ }
+ else if (ret < 0)
+ {
+ if (errno != EWOULDBLOCK && errno != EAGAIN)
+ {
+ fprintf( stderr, "Protocol error: process %p: ", process );
+ perror( "recvmsg" );
+ kill_process( process, NULL, 1 );
+ }
+ }
+ return -1;
}
/* send the wakeup signal to a thread */
@@ -280,7 +303,7 @@
int ret;
if (debug_level)
- fprintf( stderr, "%08x: *fd* %d = %d\n", (unsigned int)thread, handle, fd );
+ fprintf( stderr, "%08x: *fd* %d -> %d\n", (unsigned int)thread, handle, fd );
#ifdef HAVE_MSGHDR_ACCRIGHTS
msghdr.msg_accrightslen = sizeof(fd);