XQuartz: Changed around fd handoff model to be more robust
(cherry picked from commit 4fe605c2bc
)
This commit is contained in:
parent
183233b27b
commit
1119fe136f
|
@ -136,7 +136,7 @@ static mach_port_t checkin_or_register(char *bname) {
|
|||
}
|
||||
|
||||
/*** $DISPLAY handoff ***/
|
||||
static void accept_fd_handoff(int connected_fd) {
|
||||
static int accept_fd_handoff(int connected_fd) {
|
||||
int launchd_fd;
|
||||
|
||||
char databuf[] = "display";
|
||||
|
@ -170,16 +170,49 @@ static void accept_fd_handoff(int connected_fd) {
|
|||
|
||||
if(recvmsg(connected_fd, &msg, 0) < 0) {
|
||||
fprintf(stderr, "X11.app: Error receiving $DISPLAY file descriptor. recvmsg() error: %s\n", strerror(errno));
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
launchd_fd = *((int*)CMSG_DATA(cmsg));
|
||||
|
||||
if(launchd_fd == -1) {
|
||||
fprintf(stderr, "X11.app: Error receiving $DISPLAY file descriptor, no descriptor received? %d\n", launchd_fd);
|
||||
return;
|
||||
return launchd_fd;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
string_t filename;
|
||||
} socket_handoff_t;
|
||||
|
||||
/* This thread accepts an incoming connection and hands off the file
|
||||
* descriptor for the new connection to accept_fd_handoff()
|
||||
*/
|
||||
static void socket_handoff_thread(void *arg) {
|
||||
socket_handoff_t *handoff_data = (socket_handoff_t *)arg;
|
||||
int launchd_fd = -1;
|
||||
int connected_fd;
|
||||
|
||||
/* Now actually get the passed file descriptor from this connection
|
||||
* If we encounter an error, keep listening.
|
||||
*/
|
||||
while(launchd_fd == -1) {
|
||||
connected_fd = accept(handoff_data->fd, NULL, NULL);
|
||||
if(connected_fd == -1) {
|
||||
fprintf(stderr, "X11.app: Failed to accept incoming connection on socket (fd=%d): %s\n", handoff_data->fd, strerror(errno));
|
||||
sleep(2);
|
||||
continue;
|
||||
}
|
||||
|
||||
launchd_fd = accept_fd_handoff(connected_fd);
|
||||
if(launchd_fd == -1)
|
||||
fprintf(stderr, "X11.app: Error receiving $DISPLAY file descriptor, no descriptor received? Waiting for another connection.\n");
|
||||
|
||||
close(connected_fd);
|
||||
}
|
||||
|
||||
close(handoff_data->fd);
|
||||
unlink(handoff_data->filename);
|
||||
free(handoff_data);
|
||||
|
||||
#ifndef XQUARTZ_EXPORTS_LAUNCHD_FD
|
||||
/* TODO: Clean up this race better... giving xinitrc time to run... need to wait for 1.5 branch:
|
||||
*
|
||||
|
@ -189,72 +222,84 @@ static void accept_fd_handoff(int connected_fd) {
|
|||
* ProcSetSelectionOwner, and xfixes/select.c for an example of how to hook
|
||||
* into it.
|
||||
*/
|
||||
|
||||
|
||||
unsigned remain = 3000000;
|
||||
fprintf(stderr, "X11.app: Received new DISPLAY fd: %d ... sleeping to allow xinitrc to catchup.\n", launchd_fd);
|
||||
fprintf(stderr, "X11.app: Received new $DISPLAY fd: %d ... sleeping to allow xinitrc to catchup.\n", launchd_fd);
|
||||
while((remain = usleep(remain)) > 0);
|
||||
#endif
|
||||
|
||||
|
||||
fprintf(stderr, "X11.app Handing off fd to server thread via DarwinListenOnOpenFD(%d)\n", launchd_fd);
|
||||
DarwinListenOnOpenFD(launchd_fd);
|
||||
}
|
||||
|
||||
/* This thread accepts an incoming connection and hands off the file
|
||||
* descriptor for the new connection to accept_fd_handoff()
|
||||
*/
|
||||
static void socket_handoff_thread(void *arg) {
|
||||
int handoff_fd = *(int *)arg;
|
||||
|
||||
/* Now actually get the passed file descriptor from this connection */
|
||||
accept_fd_handoff(handoff_fd);
|
||||
|
||||
close(handoff_fd);
|
||||
}
|
||||
|
||||
kern_return_t do_prep_fd_handoff(mach_port_t port, string_t filename) {
|
||||
static int create_socket(char *filename_out) {
|
||||
struct sockaddr_un servaddr_un;
|
||||
struct sockaddr *servaddr;
|
||||
socklen_t servaddr_len;
|
||||
int handoff_fd;
|
||||
|
||||
int ret_fd;
|
||||
size_t try, try_max;
|
||||
|
||||
for(try=0, try_max=5; try < try_max; try++) {
|
||||
tmpnam(filename_out);
|
||||
|
||||
/* Setup servaddr_un */
|
||||
memset (&servaddr_un, 0, sizeof (struct sockaddr_un));
|
||||
servaddr_un.sun_family = AF_UNIX;
|
||||
strlcpy(servaddr_un.sun_path, filename_out, sizeof(servaddr_un.sun_path));
|
||||
|
||||
servaddr = (struct sockaddr *) &servaddr_un;
|
||||
servaddr_len = sizeof(struct sockaddr_un) - sizeof(servaddr_un.sun_path) + strlen(filename_out);
|
||||
|
||||
ret_fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if(ret_fd == -1) {
|
||||
fprintf(stderr, "X11.app: Failed to create socket (try %d / %d): %s - %s\n", (int)try+1, (int)try_max, filename_out, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
if(bind(ret_fd, servaddr, servaddr_len) != 0) {
|
||||
fprintf(stderr, "X11.app: Failed to bind socket: %d - %s\n", errno, strerror(errno));
|
||||
close(ret_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(listen(ret_fd, 10) != 0) {
|
||||
fprintf(stderr, "X11.app: Failed to listen to socket: %s - %d - %s\n", filename_out, errno, strerror(errno));
|
||||
close(ret_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "X11.app: Prepping for fd handoff.\n");
|
||||
fprintf(stderr, "X11.app: Listening on socket for fd handoff: (%d) %s\n", ret_fd, filename_out);
|
||||
#endif
|
||||
|
||||
return ret_fd;
|
||||
}
|
||||
|
||||
/* Initialize our data */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Setup servaddr_un */
|
||||
memset (&servaddr_un, 0, sizeof (struct sockaddr_un));
|
||||
servaddr_un.sun_family = AF_UNIX;
|
||||
strlcpy(servaddr_un.sun_path, filename, sizeof(servaddr_un.sun_path));
|
||||
|
||||
servaddr = (struct sockaddr *) &servaddr_un;
|
||||
servaddr_len = sizeof(struct sockaddr_un) - sizeof(servaddr_un.sun_path) + strlen(filename);
|
||||
kern_return_t do_request_fd_handoff_socket(mach_port_t port, string_t filename) {
|
||||
socket_handoff_t *handoff_data;
|
||||
|
||||
/* Get a fd for the handoff */
|
||||
handoff_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if(handoff_fd == -1) {
|
||||
fprintf(stderr, "X11.app: Failed to create socket: %d - %s\n", errno, strerror(errno));
|
||||
handoff_data = (socket_handoff_t *)calloc(1,sizeof(socket_handoff_t));
|
||||
if(!handoff_data) {
|
||||
fprintf(stderr, "X11.app: Error allocating memory for handoff_data\n");
|
||||
return KERN_FAILURE;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "X11.app: socket created for fd handoff: fd=%d\n", handoff_fd);
|
||||
#endif
|
||||
|
||||
if(connect(handoff_fd, servaddr, servaddr_len) < 0) {
|
||||
fprintf(stderr, "X11.app: Failed to connect to socket: %s - %d - %s\n", filename, errno, strerror(errno));
|
||||
handoff_data->fd = create_socket(handoff_data->filename);
|
||||
if(!handoff_data->fd) {
|
||||
return KERN_FAILURE;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "X11.app: Connection established for fd handoff: fd=%d\n", handoff_fd);
|
||||
#endif
|
||||
|
||||
strlcpy(filename, handoff_data->filename, STRING_T_SIZE);
|
||||
|
||||
create_thread(socket_handoff_thread, &handoff_fd);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "X11.app: Thread created for handoff. Returning success to tell caller to accept our connection and push the fd.\n");
|
||||
#endif
|
||||
create_thread(socket_handoff_thread, handoff_data);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "X11.app: Thread created for handoff. Returning success to tell caller to connect and push the fd.\n");
|
||||
#endif
|
||||
|
||||
return KERN_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@ type string_t = c_string[1024];
|
|||
type string_array_t = array[] of string_t;
|
||||
|
||||
routine start_x11_server(
|
||||
port : mach_port_t;
|
||||
port : mach_port_t;
|
||||
argv : string_array_t;
|
||||
envp : string_array_t);
|
||||
|
||||
routine prep_fd_handoff(
|
||||
port : mach_port_t;
|
||||
socket_filename : string_t);
|
||||
routine request_fd_handoff_socket (
|
||||
port : mach_port_t;
|
||||
out socket_filename : string_t);
|
||||
|
|
|
@ -116,56 +116,38 @@ static void set_x11_path() {
|
|||
}
|
||||
|
||||
#ifdef MACHO_STARTUP
|
||||
static int create_socket(char *filename_out) {
|
||||
static int connect_to_socket(const char *filename) {
|
||||
struct sockaddr_un servaddr_un;
|
||||
struct sockaddr *servaddr;
|
||||
socklen_t servaddr_len;
|
||||
int ret_fd;
|
||||
size_t try, try_max;
|
||||
|
||||
for(try=0, try_max=5; try < try_max; try++) {
|
||||
tmpnam(filename_out);
|
||||
/* Setup servaddr_un */
|
||||
memset (&servaddr_un, 0, sizeof (struct sockaddr_un));
|
||||
servaddr_un.sun_family = AF_UNIX;
|
||||
strlcpy(servaddr_un.sun_path, filename, sizeof(servaddr_un.sun_path));
|
||||
|
||||
servaddr = (struct sockaddr *) &servaddr_un;
|
||||
servaddr_len = sizeof(struct sockaddr_un) - sizeof(servaddr_un.sun_path) + strlen(filename);
|
||||
|
||||
ret_fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if(ret_fd == -1) {
|
||||
fprintf(stderr, "Xquartz: Failed to create socket: %s - %s\n", filename, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Setup servaddr_un */
|
||||
memset (&servaddr_un, 0, sizeof (struct sockaddr_un));
|
||||
servaddr_un.sun_family = AF_UNIX;
|
||||
strlcpy(servaddr_un.sun_path, filename_out, sizeof(servaddr_un.sun_path));
|
||||
|
||||
servaddr = (struct sockaddr *) &servaddr_un;
|
||||
servaddr_len = sizeof(struct sockaddr_un) - sizeof(servaddr_un.sun_path) + strlen(filename_out);
|
||||
|
||||
ret_fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if(ret_fd == -1) {
|
||||
fprintf(stderr, "Xquartz: Failed to create socket (try %d / %d): %s - %s\n", (int)try+1, (int)try_max, filename_out, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
if(bind(ret_fd, servaddr, servaddr_len) != 0) {
|
||||
fprintf(stderr, "Xquartz: Failed to bind socket: %d - %s\n", errno, strerror(errno));
|
||||
close(ret_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(listen(ret_fd, 10) != 0) {
|
||||
fprintf(stderr, "Xquartz: Failed to listen to socket: %s - %d - %s\n", filename_out, errno, strerror(errno));
|
||||
close(ret_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Xquartz: Listening on socket for fd handoff: %s\n", filename_out);
|
||||
#endif
|
||||
|
||||
return ret_fd;
|
||||
if(connect(ret_fd, servaddr, servaddr_len) < 0) {
|
||||
fprintf(stderr, "Xquartz: Failed to connect to socket: %s - %d - %s\n", filename, errno, strerror(errno));
|
||||
close(ret_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret_fd;
|
||||
}
|
||||
|
||||
static void send_fd_handoff(int handoff_fd, int launchd_fd) {
|
||||
static void send_fd_handoff(int connected_fd, int launchd_fd) {
|
||||
char databuf[] = "display";
|
||||
struct iovec iov[1];
|
||||
int connected_fd;
|
||||
|
||||
iov[0].iov_base = databuf;
|
||||
iov[0].iov_len = sizeof(databuf);
|
||||
|
@ -193,15 +175,6 @@ static void send_fd_handoff(int handoff_fd, int launchd_fd) {
|
|||
|
||||
*((int*)CMSG_DATA(cmsg)) = launchd_fd;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Xquartz: Waiting for fd handoff connection.\n");
|
||||
#endif
|
||||
connected_fd = accept(handoff_fd, NULL, NULL);
|
||||
if(connected_fd == -1) {
|
||||
fprintf(stderr, "Xquartz: Failed to accept incoming connection on socket: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Xquartz: Handoff connection established. Sending message.\n");
|
||||
#endif
|
||||
|
@ -214,9 +187,6 @@ static void send_fd_handoff(int handoff_fd, int launchd_fd) {
|
|||
fprintf(stderr, "Xquartz: Message sent. Closing.\n");
|
||||
#endif
|
||||
close(connected_fd);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Xquartz: end of send debug: %d %d %d %s\n", handoff_fd, launchd_fd, errno, strerror(errno));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -261,7 +231,7 @@ int main(int argc, char **argv, char **envp) {
|
|||
/* This forking is ugly and will be cleaned up later */
|
||||
pid_t child = fork();
|
||||
if(child == -1) {
|
||||
fprintf(stderr, "XQuartz: Could not fork: %s\n", strerror(errno));
|
||||
fprintf(stderr, "Xquartz: Could not fork: %s\n", strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -270,7 +240,7 @@ int main(int argc, char **argv, char **envp) {
|
|||
_argv[0] = x11_path;
|
||||
_argv[1] = "--listenonly";
|
||||
_argv[2] = NULL;
|
||||
fprintf(stderr, "XQuartz: Starting X server: %s --listenonly\n", x11_path);
|
||||
fprintf(stderr, "Xquartz: Starting X server: %s --listenonly\n", x11_path);
|
||||
return execvp(x11_path, _argv);
|
||||
}
|
||||
|
||||
|
@ -283,24 +253,31 @@ int main(int argc, char **argv, char **envp) {
|
|||
}
|
||||
|
||||
if(kr != KERN_SUCCESS) {
|
||||
fprintf(stderr, "XQuartz: bootstrap_look_up(): Timed out: %s\n", bootstrap_strerror(kr));
|
||||
fprintf(stderr, "Xquartz: bootstrap_look_up(): Timed out: %s\n", bootstrap_strerror(kr));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handoff the $DISPLAY FD */
|
||||
if(launchd_fd != -1) {
|
||||
int handoff_fd = create_socket(handoff_socket_filename);
|
||||
|
||||
if((handoff_fd != 0) &&
|
||||
(prep_fd_handoff(mp, handoff_socket_filename) == KERN_SUCCESS)) {
|
||||
send_fd_handoff(handoff_fd, launchd_fd);
|
||||
size_t try, try_max;
|
||||
int handoff_fd = -1;
|
||||
|
||||
for(try=0, try_max=5; try < try_max; try++) {
|
||||
if(request_fd_handoff_socket(mp, handoff_socket_filename) != KERN_SUCCESS) {
|
||||
fprintf(stderr, "Xquartz: Failed to request a socket from the server to send the $DISPLAY fd over (try %d of %d)\n", (int)try+1, (int)try_max);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
handoff_fd = connect_to_socket(handoff_socket_filename);
|
||||
if(handoff_fd == -1) {
|
||||
fprintf(stderr, "Xquartz: Failed to connect to socket (try %d of %d)\n", (int)try+1, (int)try_max);
|
||||
continue;
|
||||
}
|
||||
|
||||
send_fd_handoff(handoff_fd, launchd_fd);
|
||||
close(handoff_fd);
|
||||
unlink(handoff_socket_filename);
|
||||
} else {
|
||||
fprintf(stderr, "XQuartz: Unable to hand of $DISPLAY file descriptor\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,7 +291,7 @@ int main(int argc, char **argv, char **envp) {
|
|||
newenvp = (string_array_t)alloca(envpc * sizeof(string_t));
|
||||
|
||||
if(!newargv || !newenvp) {
|
||||
fprintf(stderr, "XQuartz: Memory allocation failure\n");
|
||||
fprintf(stderr, "Xquartz: Memory allocation failure\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
@ -327,7 +304,7 @@ int main(int argc, char **argv, char **envp) {
|
|||
|
||||
kr = start_x11_server(mp, newargv, argc, newenvp, envpc);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
fprintf(stderr, "XQuartz: start_x11_server: %s\n", mach_error_string(kr));
|
||||
fprintf(stderr, "Xquartz: start_x11_server: %s\n", mach_error_string(kr));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
|
|
Loading…
Reference in New Issue
Block a user