Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix file descriptor passing on 64-bit Linux. The fix for 64-bit OS X …

…broke it. Hopefully this time it's fixed for both platforms.
  • Loading branch information...
commit af4a8e13209f31dfd59914261266a4427a1942c6 1 parent cc52088
@FooBarWidget FooBarWidget authored
Showing with 53 additions and 65 deletions.
  1. +28 −34 ext/apache2/MessageChannel.h
  2. +25 −31 ext/passenger/native_support.c
View
62 ext/apache2/MessageChannel.h
@@ -256,33 +256,34 @@ class MessageChannel {
* @see readFileDescriptor()
*/
void writeFileDescriptor(int fileDescriptor) {
- struct {
- struct cmsghdr header;
- int fd;
- } control;
-
- control.header.cmsg_len = sizeof(control);
- control.header.cmsg_level = SOL_SOCKET;
- control.header.cmsg_type = SCM_RIGHTS;
- control.fd = fileDescriptor;
-
+ int fd;
struct msghdr msg;
struct iovec vec;
char dummy[1];
-
+ char control_data[CMSG_SPACE(sizeof(int))];
+ struct cmsghdr *control_header;
+ int *control_payload;
+
msg.msg_name = NULL;
msg.msg_namelen = 0;
-
- /* Linux and Solaris require msg_iov to be non-NULL.. */
+
+ /* Linux and Solaris require msg_iov to be non-NULL. */
dummy[0] = '\0';
vec.iov_base = dummy;
vec.iov_len = sizeof(dummy);
msg.msg_iov = &vec;
msg.msg_iovlen = 1;
-
- msg.msg_control = (caddr_t) &control;
- msg.msg_controllen = sizeof(control);
+
+ msg.msg_control = (caddr_t) control_data;
+ msg.msg_controllen = sizeof(control_data);
msg.msg_flags = 0;
+
+ control_header = CMSG_FIRSTHDR(&msg);
+ control_header->cmsg_len = CMSG_LEN(sizeof(int));
+ control_header->cmsg_level = SOL_SOCKET;
+ control_header->cmsg_type = SCM_RIGHTS;
+ control_payload = (int *) CMSG_DATA(CMSG_FIRSTHDR(&msg));
+ *control_payload = fileDescriptor;
if (sendmsg(fd, &msg, 0) == -1) {
throw SystemException("Cannot send file descriptor with sendmsg()", errno);
@@ -422,19 +423,11 @@ class MessageChannel {
* file descriptor.
*/
int readFileDescriptor() {
- struct {
- struct cmsghdr header;
- int fd;
- } control;
-
- control.header.cmsg_len = sizeof(control);
- control.header.cmsg_level = SOL_SOCKET;
- control.header.cmsg_type = SCM_RIGHTS;
- control.fd = -1;
-
struct msghdr msg;
struct iovec vec;
char dummy[1];
+ char control_data[CMSG_SPACE(sizeof(int))];
+ struct cmsghdr *control_header;
msg.msg_name = NULL;
msg.msg_namelen = 0;
@@ -445,21 +438,22 @@ class MessageChannel {
msg.msg_iov = &vec;
msg.msg_iovlen = 1;
- msg.msg_control = (caddr_t) &control;
- msg.msg_controllen = sizeof(control);
+ msg.msg_control = (caddr_t) control_data;
+ msg.msg_controllen = sizeof(control_data);
msg.msg_flags = 0;
-
+
if (recvmsg(fd, &msg, 0) == -1) {
throw SystemException("Cannot read file descriptor with recvmsg()", errno);
}
- if (msg.msg_controllen != sizeof(control)
- || control.header.cmsg_len != sizeof(control)
- || control.header.cmsg_level != SOL_SOCKET
- || control.header.cmsg_type != SCM_RIGHTS) {
+ control_header = CMSG_FIRSTHDR(&msg);
+ if (msg.msg_controllen != sizeof(control_data)
+ || control_header->cmsg_len != CMSG_LEN(sizeof(int))
+ || control_header->cmsg_level != SOL_SOCKET
+ || control_header->cmsg_type != SCM_RIGHTS) {
throw IOException("No valid file descriptor received.");
}
- return control.fd;
+ return *((int *) CMSG_DATA(control_header));
}
};
View
56 ext/passenger/native_support.c
@@ -41,33 +41,34 @@ static VALUE mNativeSupport;
static VALUE
send_fd(VALUE self, VALUE socket_fd, VALUE fd_to_send) {
int fd;
- struct {
- struct cmsghdr header;
- int fd;
- } control;
struct msghdr msg;
struct iovec vec;
char dummy[1];
-
- control.header.cmsg_len = sizeof(control);
- control.header.cmsg_level = SOL_SOCKET;
- control.header.cmsg_type = SCM_RIGHTS;
- control.fd = NUM2INT(fd_to_send);
-
+ char control_data[CMSG_SPACE(sizeof(int))];
+ struct cmsghdr *control_header;
+ int *control_payload;
+
msg.msg_name = NULL;
msg.msg_namelen = 0;
- /* Linux and Solaris require msg_iov to be non-NULL.. */
+ /* Linux and Solaris require msg_iov to be non-NULL. */
dummy[0] = '\0';
vec.iov_base = dummy;
vec.iov_len = sizeof(dummy);
msg.msg_iov = &vec;
msg.msg_iovlen = 1;
- msg.msg_control = (caddr_t) &control;
- msg.msg_controllen = sizeof(control);
+ msg.msg_control = (caddr_t) control_data;
+ msg.msg_controllen = sizeof(control_data);
msg.msg_flags = 0;
+ control_header = CMSG_FIRSTHDR(&msg);
+ control_header->cmsg_len = CMSG_LEN(sizeof(int));
+ control_header->cmsg_level = SOL_SOCKET;
+ control_header->cmsg_type = SCM_RIGHTS;
+ control_payload = (int *) CMSG_DATA(CMSG_FIRSTHDR(&msg));
+ *control_payload = NUM2INT(fd_to_send);
+
if (sendmsg(NUM2INT(socket_fd), &msg, 0) == -1) {
rb_sys_fail("sendmsg(2)");
return Qnil;
@@ -88,19 +89,11 @@ send_fd(VALUE self, VALUE socket_fd, VALUE fd_to_send) {
*/
static VALUE
recv_fd(VALUE self, VALUE socket_fd) {
- struct {
- struct cmsghdr header;
- int fd;
- } control;
-
- control.header.cmsg_len = sizeof(control);
- control.header.cmsg_level = SOL_SOCKET;
- control.header.cmsg_type = SCM_RIGHTS;
- control.fd = -1;
-
struct msghdr msg;
struct iovec vec;
char dummy[1];
+ char control_data[CMSG_SPACE(sizeof(int))];
+ struct cmsghdr *control_header;
msg.msg_name = NULL;
msg.msg_namelen = 0;
@@ -111,23 +104,24 @@ recv_fd(VALUE self, VALUE socket_fd) {
msg.msg_iov = &vec;
msg.msg_iovlen = 1;
- msg.msg_control = (caddr_t) &control;
- msg.msg_controllen = sizeof(control);
+ msg.msg_control = (caddr_t) control_data;
+ msg.msg_controllen = sizeof(control_data);
msg.msg_flags = 0;
-
+
if (recvmsg(NUM2INT(socket_fd), &msg, 0) == -1) {
rb_sys_fail("Cannot read file descriptor with recvmsg()");
return Qnil;
}
- if (msg.msg_controllen != sizeof(control)
- || control.header.cmsg_len != sizeof(control)
- || control.header.cmsg_level != SOL_SOCKET
- || control.header.cmsg_type != SCM_RIGHTS) {
+ control_header = CMSG_FIRSTHDR(&msg);
+ if (msg.msg_controllen != sizeof(control_data)
+ || control_header->cmsg_len != CMSG_LEN(sizeof(int))
+ || control_header->cmsg_level != SOL_SOCKET
+ || control_header->cmsg_type != SCM_RIGHTS) {
rb_sys_fail("No valid file descriptor received.");
return Qnil;
}
- return INT2NUM(control.fd);
+ return INT2NUM(*((int *) CMSG_DATA(control_header)));
}
/*
Please sign in to comment.
Something went wrong with that request. Please try again.