server: Make the fd passing code slightly more portable.

This commit is contained in:
Alexandre Julliard 2010-09-30 11:53:07 +02:00
parent 19da00a6a3
commit 179715251d
2 changed files with 78 additions and 86 deletions

View File

@ -99,20 +99,6 @@ static const enum cpu_type client_cpu = CPU_ARM;
unsigned int server_cpus = 0; unsigned int server_cpus = 0;
int is_wow64 = FALSE; int is_wow64 = FALSE;
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
/* data structure used to pass an fd with sendmsg/recvmsg */
struct cmsg_fd
{
struct
{
size_t len; /* size of structure */
int level; /* SOL_SOCKET */
int type; /* SCM_RIGHTS */
} header;
int fd; /* fd to pass */
};
#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
timeout_t server_start_time = 0; /* time of server startup */ timeout_t server_start_time = 0; /* time of server startup */
sigset_t server_block_set; /* signals to block during server calls */ sigset_t server_block_set; /* signals to block during server calls */
@ -334,34 +320,35 @@ void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sig
*/ */
void CDECL wine_server_send_fd( int fd ) void CDECL wine_server_send_fd( int fd )
{ {
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
struct cmsg_fd cmsg;
#endif
struct send_fd data; struct send_fd data;
struct msghdr msghdr; struct msghdr msghdr;
struct iovec vec; struct iovec vec;
int ret; int ret;
vec.iov_base = (void *)&data; #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
vec.iov_len = sizeof(data); msghdr.msg_accrights = (void *)&fd;
msghdr.msg_accrightslen = sizeof(fd);
#else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
char cmsg_buffer[256];
struct cmsghdr *cmsg;
msghdr.msg_control = cmsg_buffer;
msghdr.msg_controllen = sizeof(cmsg_buffer);
msghdr.msg_flags = 0;
cmsg = CMSG_FIRSTHDR( &msghdr );
cmsg->cmsg_len = CMSG_LEN( sizeof(fd) );
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = fd;
msghdr.msg_controllen = cmsg->cmsg_len;
#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
msghdr.msg_name = NULL; msghdr.msg_name = NULL;
msghdr.msg_namelen = 0; msghdr.msg_namelen = 0;
msghdr.msg_iov = &vec; msghdr.msg_iov = &vec;
msghdr.msg_iovlen = 1; msghdr.msg_iovlen = 1;
#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS vec.iov_base = (void *)&data;
msghdr.msg_accrights = (void *)&fd; vec.iov_len = sizeof(data);
msghdr.msg_accrightslen = sizeof(fd);
#else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
cmsg.header.len = sizeof(cmsg.header) + sizeof(fd);
cmsg.header.level = SOL_SOCKET;
cmsg.header.type = SCM_RIGHTS;
cmsg.fd = fd;
msghdr.msg_control = &cmsg;
msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd);
msghdr.msg_flags = 0;
#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
data.tid = GetCurrentThreadId(); data.tid = GetCurrentThreadId();
data.fd = fd; data.fd = fd;
@ -385,24 +372,16 @@ void CDECL wine_server_send_fd( int fd )
static int receive_fd( obj_handle_t *handle ) static int receive_fd( obj_handle_t *handle )
{ {
struct iovec vec; struct iovec vec;
int ret, fd; struct msghdr msghdr;
int ret, fd = -1;
#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
struct msghdr msghdr;
fd = -1;
msghdr.msg_accrights = (void *)&fd; msghdr.msg_accrights = (void *)&fd;
msghdr.msg_accrightslen = sizeof(fd); msghdr.msg_accrightslen = sizeof(fd);
#else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ #else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
struct msghdr msghdr; char cmsg_buffer[256];
struct cmsg_fd cmsg; msghdr.msg_control = cmsg_buffer;
msghdr.msg_controllen = sizeof(cmsg_buffer);
cmsg.header.len = sizeof(cmsg.header) + sizeof(fd);
cmsg.header.level = SOL_SOCKET;
cmsg.header.type = SCM_RIGHTS;
cmsg.fd = -1;
msghdr.msg_control = &cmsg;
msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd);
msghdr.msg_flags = 0; msghdr.msg_flags = 0;
#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
@ -418,8 +397,13 @@ static int receive_fd( obj_handle_t *handle )
if ((ret = recvmsg( fd_socket, &msghdr, MSG_CMSG_CLOEXEC )) > 0) if ((ret = recvmsg( fd_socket, &msghdr, MSG_CMSG_CLOEXEC )) > 0)
{ {
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
fd = cmsg.fd; struct cmsghdr *cmsg;
#endif for (cmsg = CMSG_FIRSTHDR( &msghdr ); cmsg; cmsg = CMSG_NXTHDR( &msghdr, cmsg ))
{
if (cmsg->cmsg_level != SOL_SOCKET) continue;
if (cmsg->cmsg_type == SCM_RIGHTS) fd = *(int *)CMSG_DATA(cmsg);
}
#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
if (fd != -1) fcntl( fd, F_SETFD, FD_CLOEXEC ); /* in case MSG_CMSG_CLOEXEC is not supported */ if (fd != -1) fcntl( fd, F_SETFD, FD_CLOEXEC ); /* in case MSG_CMSG_CLOEXEC is not supported */
return fd; return fd;
} }

View File

@ -126,23 +126,6 @@ int config_dir_fd = -1; /* file descriptor for the config dir */
static struct master_socket *master_socket; /* the master socket object */ static struct master_socket *master_socket; /* the master socket object */
static struct timeout_user *master_timeout; static struct timeout_user *master_timeout;
/* socket communication static structures */
static struct iovec myiovec;
static struct msghdr msghdr;
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
struct cmsg_fd
{
struct
{
size_t len; /* size of structure */
int level; /* SOL_SOCKET */
int type; /* SCM_RIGHTS */
} header;
int fd; /* fd to pass */
};
static struct cmsg_fd cmsg = { { sizeof(cmsg.header) + sizeof(cmsg.fd), SOL_SOCKET, SCM_RIGHTS }, -1 };
#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
/* complain about a protocol error and terminate the client connection */ /* complain about a protocol error and terminate the client connection */
void fatal_protocol_error( struct thread *thread, const char *err, ... ) void fatal_protocol_error( struct thread *thread, const char *err, ... )
{ {
@ -359,25 +342,41 @@ error:
/* receive a file descriptor on the process socket */ /* receive a file descriptor on the process socket */
int receive_fd( struct process *process ) int receive_fd( struct process *process )
{ {
struct iovec vec;
struct send_fd data; struct send_fd data;
int fd, ret; struct msghdr msghdr;
int fd = -1, ret;
#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
msghdr.msg_accrightslen = sizeof(int); msghdr.msg_accrightslen = sizeof(int);
msghdr.msg_accrights = (void *)&fd; msghdr.msg_accrights = (void *)&fd;
#else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ #else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
msghdr.msg_control = &cmsg; char cmsg_buffer[256];
msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd); msghdr.msg_control = cmsg_buffer;
cmsg.fd = -1; msghdr.msg_controllen = sizeof(cmsg_buffer);
msghdr.msg_flags = 0;
#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
myiovec.iov_base = (void *)&data; msghdr.msg_name = NULL;
myiovec.iov_len = sizeof(data); msghdr.msg_namelen = 0;
msghdr.msg_iov = &vec;
msghdr.msg_iovlen = 1;
vec.iov_base = (void *)&data;
vec.iov_len = sizeof(data);
ret = recvmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 ); ret = recvmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 );
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
fd = cmsg.fd; if (ret > 0)
#endif {
struct cmsghdr *cmsg;
for (cmsg = CMSG_FIRSTHDR( &msghdr ); cmsg; cmsg = CMSG_NXTHDR( &msghdr, cmsg ))
{
if (cmsg->cmsg_level != SOL_SOCKET) continue;
if (cmsg->cmsg_type == SCM_RIGHTS) fd = *(int *)CMSG_DATA(cmsg);
}
}
#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
if (ret == sizeof(data)) if (ret == sizeof(data))
{ {
@ -412,6 +411,7 @@ int receive_fd( struct process *process )
{ {
fprintf( stderr, "Protocol error: process %04x: partial recvmsg %d for fd\n", fprintf( stderr, "Protocol error: process %04x: partial recvmsg %d for fd\n",
process->id, ret ); process->id, ret );
if (fd != -1) close( fd );
kill_process( process, 1 ); kill_process( process, 1 );
} }
else else
@ -429,23 +429,37 @@ int receive_fd( struct process *process )
/* send an fd to a client */ /* send an fd to a client */
int send_client_fd( struct process *process, int fd, obj_handle_t handle ) int send_client_fd( struct process *process, int fd, obj_handle_t handle )
{ {
struct iovec vec;
struct msghdr msghdr;
int ret; int ret;
if (debug_level)
fprintf( stderr, "%04x: *fd* %04x -> %d\n",
current ? current->id : process->id, handle, fd );
#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS #ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
msghdr.msg_accrightslen = sizeof(fd); msghdr.msg_accrightslen = sizeof(fd);
msghdr.msg_accrights = (void *)&fd; msghdr.msg_accrights = (void *)&fd;
#else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ #else /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
msghdr.msg_control = &cmsg; char cmsg_buffer[256];
msghdr.msg_controllen = sizeof(cmsg.header) + sizeof(fd); struct cmsghdr *cmsg;
cmsg.fd = fd; msghdr.msg_control = cmsg_buffer;
msghdr.msg_controllen = sizeof(cmsg_buffer);
msghdr.msg_flags = 0;
cmsg = CMSG_FIRSTHDR( &msghdr );
cmsg->cmsg_len = CMSG_LEN( sizeof(fd) );
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = fd;
msghdr.msg_controllen = cmsg->cmsg_len;
#endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */ #endif /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
myiovec.iov_base = (void *)&handle; msghdr.msg_name = NULL;
myiovec.iov_len = sizeof(handle); msghdr.msg_namelen = 0;
msghdr.msg_iov = &vec;
msghdr.msg_iovlen = 1;
vec.iov_base = (void *)&handle;
vec.iov_len = sizeof(handle);
if (debug_level)
fprintf( stderr, "%04x: *fd* %04x -> %d\n", current ? current->id : process->id, handle, fd );
ret = sendmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 ); ret = sendmsg( get_unix_fd( process->msg_fd ), &msghdr, 0 );
@ -797,12 +811,6 @@ void open_master_socket(void)
acquire_lock(); acquire_lock();
} }
/* setup msghdr structure constant fields */
msghdr.msg_name = NULL;
msghdr.msg_namelen = 0;
msghdr.msg_iov = &myiovec;
msghdr.msg_iovlen = 1;
/* init the process tracing mechanism */ /* init the process tracing mechanism */
init_tracing_mechanism(); init_tracing_mechanism();
} }