XQuartz: Starting to work on the new Mach IPC startup stuff for better launchd, ApplicationServices, and Dock support

(cherry picked from commit 9b67fca9b7)
This commit is contained in:
Jeremy Huddleston 2008-05-09 16:44:31 -07:00
parent 04211c3532
commit a7800d9355
5 changed files with 232 additions and 6 deletions

4
.gitignore vendored
View File

@ -278,6 +278,10 @@ hw/xprint/doc/Xprt.1x
hw/xprint/doc/Xprt.man
hw/xprint/dpmsstubs-wrapper.c
hw/xprint/miinitext-wrapper.c
hw/xquartz/mach-startup/mach_startup.h
hw/xquartz/mach-startup/mach_startupServer.c
hw/xquartz/mach-startup/mach_startupServer.h
hw/xquartz/mach-startup/mach_startupUser.c
hw/xquartz/mach-startup/X11
hw/xquartz/mach-startup/Xquartz
hw/xquartz/doc/Xquartz.1

View File

@ -5,9 +5,13 @@ AM_CPPFLAGS = \
x11appdir = $(APPLE_APPLICATIONS_DIR)/X11.app/Contents/MacOS
x11app_PROGRAMS = X11
X11_SOURCES = \
dist_X11_SOURCES = \
bundle-main.c
nodist_X11_SOURCES = \
mach_startupServer.c \
mach_startupUser.c
X11_LDADD = \
$(top_builddir)/hw/xquartz/libXquartz.la \
$(top_builddir)/hw/xquartz/xpr/libXquartzXpr.la \
@ -27,8 +31,28 @@ X11_LDFLAGS = \
bin_PROGRAMS = Xquartz
Xquartz_SOURCES = \
dist_Xquartz_SOURCES = \
stub.c
nodist_Xquartz_SOURCES = \
mach_startupUser.c
Xquartz_LDFLAGS = \
-Wl,-framework,CoreServices
BUILT_SOURCES = \
mach_startupServer.c \
mach_startupUser.c \
mach_startupServer.h \
mach_startup.h
CLEANFILES = \
$(BUILT_SOURCES)
$(BUILT_SOURCES): mach_startup.defs
mig -sheader mach_startupServer.h mach_startup.defs
EXTRA_DIST = \
mach_startup.defs \
mach_startup_types.h

View File

@ -33,9 +33,16 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <CoreFoundation/CoreFoundation.h>
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <servers/bootstrap.h>
#include "mach_startup.h"
#include "mach_startupServer.h"
#define DEFAULT_CLIENT "/usr/X11/bin/xterm"
#define DEFAULT_STARTX "/usr/X11/bin/startx"
#define DEFAULT_SHELL "/bin/sh"
@ -43,12 +50,146 @@
static int execute(const char *command);
static char *command_from_prefs(const char *key, const char *default_value);
/* This is in quartzStartup.c */
int server_main(int argc, char **argv, char **envp);
struct arg {
int argc;
char **argv;
char **envp;
};
/*** Mach-O IPC Stuffs ***/
union MaxMsgSize {
union __RequestUnion__mach_startup_subsystem req;
union __ReplyUnion__mach_startup_subsystem rep;
};
kern_return_t do_start_x11_server(mach_port_t port, string_array_t argv,
mach_msg_type_number_t argvCnt,
string_array_t envp,
mach_msg_type_number_t envpCnt) {
if(server_main(argvCnt, argv, envp) == 0)
return KERN_SUCCESS;
else
return KERN_FAILURE;
}
kern_return_t do_exit(mach_port_t port, int value) {
exit(value);
}
static mach_port_t checkin_or_register(char *bname) {
kern_return_t kr;
mach_port_t mp;
/* If we're started by launchd or the old mach_init */
kr = bootstrap_check_in(bootstrap_port, bname, &mp);
if (kr == KERN_SUCCESS)
return mp;
/* We probably were not started by launchd or the old mach_init */
kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mp);
if (kr != KERN_SUCCESS) {
fprintf(stderr, "mach_port_allocate(): %s\n", mach_error_string(kr));
exit(EXIT_FAILURE);
}
kr = mach_port_insert_right(mach_task_self(), mp, mp, MACH_MSG_TYPE_MAKE_SEND);
if (kr != KERN_SUCCESS) {
fprintf(stderr, "mach_port_insert_right(): %s\n", mach_error_string(kr));
exit(EXIT_FAILURE);
}
kr = bootstrap_register(bootstrap_port, bname, mp);
if (kr != KERN_SUCCESS) {
fprintf(stderr, "bootstrap_register(): %s\n", mach_error_string(kr));
exit(EXIT_FAILURE);
}
return mp;
}
/*** Pthread Magics ***/
static pthread_t create_thread(void *func, void *arg) {
pthread_attr_t attr;
pthread_t tid;
pthread_attr_init (&attr);
pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&tid, &attr, func, arg);
pthread_attr_destroy (&attr);
return tid;
}
/*** Main ***/
static int execute(const char *command);
static char *command_from_prefs(const char *key, const char *default_value);
#ifdef NEW_LAUNCH_METHOD
static void startup_trigger_thread(void *arg) {
struct arg args = *((struct arg *)arg);
free(arg);
startup_trigger(args.argc, args.argv, args.envp);
}
int main(int argc, char **argv, char **envp) {
BOOL listenOnly = FALSE;
int i;
for(i=1; i < argc; i++) {
if(!strcmp(argv[i], "--listenonly")) {
listenOnly = TRUE;
break;
}
}
/* Check if we need to do something other than listen, and make another
* thread handle it.
*/
if(!listenOnly) {
struct arg *args = (struct arg*)malloc(sizeof(struct arg));
if(!args)
FatalError("Could not allocate memory.\n");
args->argc = argc;
args->argv = argv;
args->envp = envp;
create_thread(startup_trigger_thread, args);
} else {
/* TODO: This should actually fall through rather than be the else
* case once we figure out how to get the stub to pass the
* file descriptor. For now, we only listen if we are explicitly
* told to.
*/
mach_msg_size_t mxmsgsz = sizeof(union MaxMsgSize) + MAX_TRAILER_SIZE;
mach_port_t mp = checkin_or_register(SERVER_BOOTSTRAP_NAME);
kern_return_t kr;
/* Main event loop */
kr = mach_msg_server(mach_startup_server, mxmsgsz, mp, 0);
if (kr != KERN_SUCCESS) {
asl_log(NULL, NULL, ASL_LEVEL_ERR,
"org.x.X11(mp): %s\n", mach_error_string(kr));
exit(EXIT_FAILURE);
}
}
return EXIT_SUCCESS;
}
int startup_trigger(int argc, char **argv, char **envp) {
#else
int main(int argc, char **argv, char **envp) {
#endif
Display *display;
const char *s;
size_t i;
fprintf(stderr, "X11.app: main(): argc=%d\n", argc);
for(i=0; i < argc; i++) {
@ -57,7 +198,15 @@ int main(int argc, char **argv, char **envp) {
/* Take care of the case where we're called like a normal DDX */
if(argc > 1 && argv[1][0] == ':') {
exit(server_main(argc, argv, envp));
#ifdef NEW_LAUNCH_METHOD
/* We need to count envp */
int envpc;
for(envpc=0; envp[envpc]; envpc++);
return start_x11_server(argc, argv, envp, envpc);
#else
return server_main(argc, argv, envp);
#endif
}
/* If we have a process serial number and it's our only arg, act as if
@ -70,7 +219,7 @@ int main(int argc, char **argv, char **envp) {
fprintf(stderr, "X11.app: Closing the display and sleeping for 2s to allow the X server to start up.\n");
/* Could open the display, start the launcher */
XCloseDisplay(display);
/* Give 2 seconds for the server to start...
* TODO: *Really* fix this race condition
*/
@ -78,7 +227,7 @@ int main(int argc, char **argv, char **envp) {
return execute(command_from_prefs("app_to_run", DEFAULT_CLIENT));
}
}
/* Start the server */
if((s = getenv("DISPLAY"))) {
fprintf(stderr, "X11.app: Could not connect to server (DISPLAY=\"%s\", unsetting). Starting X server.\n", s);

View File

@ -0,0 +1,41 @@
/* Copyright (c) 2008 Apple Inc.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
* HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above
* copyright holders shall not be used in advertising or otherwise to
* promote the sale, use or other dealings in this Software without
* prior written authorization.
*/
#include <mach/std_types.defs>
#include <mach/mach_types.defs>
import "mach_startup_types.h";
subsystem mach_startup 1000;
serverprefix do_;
type string_array_t = array[] of c_string[1024];
routine start_x11_server(
port : mach_port_t;
argv : string_array_t;
envp : string_array_t);

View File

@ -0,0 +1,8 @@
#ifndef _MACH_STARTUP_TYPES_H_
#define _MACH_STARTUP_TYPES_H_
#define SERVER_BOOTSTRAP_NAME "org.x.X11"
typedef char ** string_array_t;
#endif