[AD] OSX Dead bootstrap fix |
[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
Please find below a patch to avoid the dead bootstrap issue as
discussed on a.cc. It also cleans up the dock notification code, and
allows command line apps (with SYSTEM_NONE) to run without the dock
being notified at all (resulting in faster start-up times, and avoiding
Dock crashes if apps start and terminate very quickly)
Pete
Index: src/macosx/main.m
===================================================================
RCS file: /cvsroot/alleg/allegro/src/macosx/main.m,v
retrieving revision 1.25
diff -u -b -r1.25 main.m
--- src/macosx/main.m 26 Jun 2005 14:50:51 -0000 1.25
+++ src/macosx/main.m 12 Jul 2005 18:18:48 -0000
@@ -37,18 +37,7 @@
static int refresh_rate = 70;
-/* These are used to warn the dock about the application */
-typedef struct CPSProcessSerNum
-{
- UInt32 lo;
- UInt32 hi;
-} CPSProcessSerNum;
-
-extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
-extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn,
UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
-extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
-
-
+int osx_bootstrap_ok(void);
@implementation AllegroAppDelegate
@@ -156,6 +145,13 @@
}
+/* Call the user main() */
+static void call_user_main(void) {
+ int (*real_main) (int, char*[]) =
+ (int (*) (int, char*[])) _mangled_main_address;
+ exit(real_main(__crt0_argc, __crt0_argv));
+}
+
/* app_main:
* Thread dedicated to the user program; real main() gets called here.
@@ -163,11 +159,7 @@
+ (void)app_main: (id)arg
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- int (*real_main) (int, char*[]) = (int (*) (int, char*[]))
_mangled_main_address;
-
- /* Call the user main() */
- exit(real_main(__crt0_argc, __crt0_argv));
-
+ call_user_main();
[pool release];
}
@@ -206,22 +198,15 @@
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
AllegroAppDelegate *app_delegate = [[AllegroAppDelegate alloc]
init];
- CPSProcessSerNum psn;
NSMenu *menu;
NSMenuItem *menu_item, *temp_item;
__crt0_argc = argc;
__crt0_argv = argv;
- [NSApplication sharedApplication];
+ if (!osx_bootstrap_ok()) /* not safe to use NSApplication */
+ call_user_main();
- /* Tell the dock about us; the origins of this hack are unknown,
but it's
- * currently the only way to make a Cocoa app to work when started
from a
- * console.
- */
- if ((!CPSGetCurrentProcess(&psn)) &&
- (!CPSEnableForegroundOperation(&psn, 0x03, 0x3C, 0x2C, 0x1103))
&&
- (!CPSSetFrontProcess(&psn)))
[NSApplication sharedApplication];
/* Creates a custom application menu */
Index: src/macosx/system.m
===================================================================
RCS file: /cvsroot/alleg/allegro/src/macosx/system.m,v
retrieving revision 1.28
diff -u -b -r1.28 system.m
--- src/macosx/system.m 26 Jun 2005 14:50:51 -0000 1.28
+++ src/macosx/system.m 12 Jul 2005 18:18:51 -0000
@@ -320,7 +320,53 @@
[pool release];
}
-
+/* osx_tell_dock:
+ * Tell the dock about us; the origins of this hack are unknown, but
it's
+ * currently the only way to make a Cocoa app to work when started
from a
+ * console.
+ * For the future, (10.3 and above) investigate TranformProcessType in
the
+ * HIServices framework.
+ */
+static void osx_tell_dock(void)
+{
+ struct CPSProcessSerNum
+ {
+ UInt32 lo;
+ UInt32 hi;
+ } psn;
+ extern OSErr CPSGetCurrentProcess(struct CPSProcessSerNum *psn);
+ extern OSErr CPSEnableForegroundOperation(struct CPSProcessSerNum
*psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
+ extern OSErr CPSSetFrontProcess(struct CPSProcessSerNum *psn);
+
+ if ((!CPSGetCurrentProcess(&psn)) &&
+ (!CPSEnableForegroundOperation(&psn, 0x03, 0x3C, 0x2C, 0x1103))
&&
+ (!CPSSetFrontProcess(&psn)))
+ [NSApplication sharedApplication];
+}
+/* osx_bootstrap_ok:
+ * Check if the current bootstrap context is privilege. If it's not,
we can't
+ * use NSApplication, and instead have to go directly to main.
+ * Returns 1 if ok, 0 if not.
+ */
+#include <CoreFoundation/CoreFoundation.h>
+#include <mach/mach_port.h>
+#include <servers/bootstrap.h>
+
+
+int osx_bootstrap_ok(void) {
+ static int _ok=-1;
+ mach_port_t bp;
+ kern_return_t ret;
+ CFMachPortRef cfport;
+ /* If have tested once, just return that answer */
+ if (_ok>=0) return _ok;
+ cfport = CFMachPortCreate(NULL, NULL, NULL, NULL);
+ task_get_bootstrap_port(mach_task_self(), &bp);
+ ret = bootstrap_register(bp, "bootstrap-ok-test",
+ CFMachPortGetPort(cfport));
+ _ok= (ret == KERN_SUCCESS) ? 1 : 0;
+ return _ok;
+}
/* osx_sys_init:
* Initalizes the MacOS X system driver.
@@ -331,6 +377,15 @@
AL_CONST char *exe_name;
char resource_dir[1024];
+ /* If we're in
+ * the 'dead bootstrap' environment, the Mac
+ * driver won't work
+ */
+
+ if (!osx_bootstrap_ok()) {
+ return -1;
+ }
+
/* Install emergency-exit signal handlers */
old_sig_abrt = signal(SIGABRT, osx_signal_handler);
old_sig_fpe = signal(SIGFPE, osx_signal_handler);
@@ -340,6 +395,8 @@
old_sig_int = signal(SIGINT, osx_signal_handler);
old_sig_quit = signal(SIGQUIT, osx_signal_handler);
+ osx_tell_dock();
+
/* Get into bundle resource directory if appropriate */
if (osx_bundle) {
exe_name = [[osx_bundle executablePath] lossyCString];