aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llappviewermacosx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llappviewermacosx.cpp')
-rw-r--r--linden/indra/newview/llappviewermacosx.cpp207
1 files changed, 189 insertions, 18 deletions
diff --git a/linden/indra/newview/llappviewermacosx.cpp b/linden/indra/newview/llappviewermacosx.cpp
index 68c3a16..0e5062d 100644
--- a/linden/indra/newview/llappviewermacosx.cpp
+++ b/linden/indra/newview/llappviewermacosx.cpp
@@ -4,7 +4,7 @@
4 * 4 *
5 * $LicenseInfo:firstyear=2007&license=viewergpl$ 5 * $LicenseInfo:firstyear=2007&license=viewergpl$
6 * 6 *
7 * Copyright (c) 2007-2008, Linden Research, Inc. 7 * Copyright (c) 2007-2009, Linden Research, Inc.
8 * 8 *
9 * Second Life Viewer Source Code 9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab 10 * The source code in this file ("Source Code") is provided by Linden Lab
@@ -48,12 +48,25 @@
48#include "llurldispatcher.h" 48#include "llurldispatcher.h"
49#include <Carbon/Carbon.h> 49#include <Carbon/Carbon.h>
50#include "lldir.h" 50#include "lldir.h"
51#include <signal.h>
52
51namespace 53namespace
52{ 54{
53 // The command line args stored. 55 // The command line args stored.
54 // They are not used immediately by the app. 56 // They are not used immediately by the app.
55 int gArgC; 57 int gArgC;
56 char** gArgV; 58 char** gArgV;
59
60 bool sCrashReporterIsRunning = false;
61
62 OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
63 {
64 OSErr result = noErr;
65
66 LLAppViewer::instance()->userQuit();
67
68 return(result);
69 }
57} 70}
58 71
59int main( int argc, char **argv ) 72int main( int argc, char **argv )
@@ -193,22 +206,189 @@ bool LLAppViewerMacOSX::initParseCommandLine(LLCommandLineParser& clp)
193 return true; 206 return true;
194} 207}
195 208
209// *FIX:Mani It would be nice to provide a clean interface to get the
210// default_unix_signal_handler for the LLApp class.
211extern void default_unix_signal_handler(int, siginfo_t *, void *);
212bool LLAppViewerMacOSX::restoreErrorTrap()
213{
214 // This method intends to reinstate signal handlers.
215 // *NOTE:Mani It was found that the first execution of a shader was overriding
216 // our initial signal handlers somehow.
217 // This method will be called (at least) once per mainloop execution.
218 // *NOTE:Mani The signals used below are copied over from the
219 // setup_signals() func in LLApp.cpp
220 // LLApp could use some way of overriding that func, but for this viewer
221 // fix I opt to avoid affecting the server code.
222
223 // Set up signal handlers that may result in program termination
224 //
225 struct sigaction act;
226 struct sigaction old_act;
227 act.sa_sigaction = default_unix_signal_handler;
228 sigemptyset( &act.sa_mask );
229 act.sa_flags = SA_SIGINFO;
230
231 unsigned int reset_count = 0;
232
233#define SET_SIG(S) sigaction(SIGABRT, &act, &old_act); \
234 if((unsigned int)act.sa_sigaction != (unsigned int) old_act.sa_sigaction) \
235 ++reset_count;
236 // Synchronous signals
237 SET_SIG(SIGABRT)
238 SET_SIG(SIGALRM)
239 SET_SIG(SIGBUS)
240 SET_SIG(SIGFPE)
241 SET_SIG(SIGHUP)
242 SET_SIG(SIGILL)
243 SET_SIG(SIGPIPE)
244 SET_SIG(SIGSEGV)
245 SET_SIG(SIGSYS)
246
247 SET_SIG(LL_HEARTBEAT_SIGNAL)
248 SET_SIG(LL_SMACKDOWN_SIGNAL)
249
250 // Asynchronous signals that are normally ignored
251 SET_SIG(SIGCHLD)
252 SET_SIG(SIGUSR2)
253
254 // Asynchronous signals that result in attempted graceful exit
255 SET_SIG(SIGHUP)
256 SET_SIG(SIGTERM)
257 SET_SIG(SIGINT)
258
259 // Asynchronous signals that result in core
260 SET_SIG(SIGQUIT)
261#undef SET_SIG
262
263 return reset_count == 0;
264}
265
196void LLAppViewerMacOSX::handleSyncCrashTrace() 266void LLAppViewerMacOSX::handleSyncCrashTrace()
197{ 267{
198 // do nothing 268 // do nothing
199} 269}
200 270
201void LLAppViewerMacOSX::handleCrashReporting() 271static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef,
272 EventRef inEvent,
273 void* inUserData)
274{
275 ProcessSerialNumber psn;
276
277 GetEventParameter(inEvent,
278 kEventParamProcessID,
279 typeProcessSerialNumber,
280 NULL,
281 sizeof(psn),
282 NULL,
283 &psn);
284
285 if( GetEventKind(inEvent) == kEventAppTerminated )
286 {
287 Boolean matching_psn = FALSE;
288 OSErr os_result = SameProcess(&psn, (ProcessSerialNumber*)inUserData, &matching_psn);
289 if(os_result >= 0 && matching_psn)
290 {
291 sCrashReporterIsRunning = false;
292 }
293 }
294 return noErr;
295}
296
297void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze)
202{ 298{
203 // Macintosh 299 // This used to use fork&exec, but is switched to LSOpenApplication to
300 // Make sure the crash reporter launches in front of the SL window.
301
204 std::string command_str; 302 std::string command_str;
205 command_str += "open mac-crash-logger.app"; 303 //command_str = "open Second Life.app/Contents/Resources/mac-crash-logger.app";
304 command_str = "mac-crash-logger.app/Contents/MacOS/mac-crash-logger";
206 305
207 clear_signals(); 306 FSRef appRef;
208 llinfos << "Launching crash reporter using: '" << command_str << "'" << llendl; 307 Boolean isDir = 0;
209 system(command_str.c_str()); /* Flawfinder: ignore */ 308 OSStatus os_result = FSPathMakeRef((UInt8*)command_str.c_str(),
210 llinfos << "returned from crash reporter... dying" << llendl; 309 &appRef,
211 _exit(1); 310 &isDir);
311 if(os_result >= 0)
312 {
313 LSApplicationParameters appParams;
314 memset(&appParams, 0, sizeof(appParams));
315 appParams.version = 0;
316 appParams.flags = kLSLaunchNoParams | kLSLaunchStartClassic;
317 appParams.application = &appRef;
318
319 if(reportFreeze)
320 {
321 // Make sure freeze reporting launches the crash logger synchronously, lest
322 // Log files get changed by SL while the logger is running.
323
324 // *NOTE:Mani A better way - make a copy of the data that the crash reporter will send
325 // and let SL go about its business. This way makes the mac work like windows and linux
326 // and is the smallest patch for the issue.
327 sCrashReporterIsRunning = true;
328 ProcessSerialNumber o_psn;
329
330 static EventHandlerRef sCarbonEventsRef = NULL;
331 static const EventTypeSpec kEvents[] =
332 {
333 { kEventClassApplication, kEventAppTerminated }
334 };
335
336 // Install the handler to detect crash logger termination
337 InstallEventHandler(GetApplicationEventTarget(),
338 (EventHandlerUPP) CarbonEventHandler,
339 GetEventTypeCount(kEvents),
340 kEvents,
341 &o_psn,
342 &sCarbonEventsRef
343 );
344
345 // Remove, temporarily the quit handler - which has *crash* behavior before
346 // the mainloop gets running!
347 AERemoveEventHandler(kCoreEventClass,
348 kAEQuitApplication,
349 NewAEEventHandlerUPP(AEQuitHandler),
350 false);
351
352 // Launch the crash reporter.
353 os_result = LSOpenApplication(&appParams, &o_psn);
354
355 if(os_result >= 0)
356 {
357 EventRecord evt;
358 while(sCrashReporterIsRunning)
359 {
360 while(WaitNextEvent(osMask, &evt, 0, NULL))
361 {
362 // null op!?!
363 }
364 }
365 }
366
367 // Re-install the apps quit handler.
368 AEInstallEventHandler(kCoreEventClass,
369 kAEQuitApplication,
370 NewAEEventHandlerUPP(AEQuitHandler),
371 0,
372 false);
373
374 // Remove the crash reporter quit handler.
375 RemoveEventHandler(sCarbonEventsRef);
376 }
377 else
378 {
379 appParams.flags |= kLSLaunchAsync;
380 clear_signals();
381
382 ProcessSerialNumber o_psn;
383 os_result = LSOpenApplication(&appParams, &o_psn);
384 }
385
386 }
387
388 if(!reportFreeze)
389 {
390 _exit(1);
391 }
212} 392}
213 393
214std::string LLAppViewerMacOSX::generateSerialNumber() 394std::string LLAppViewerMacOSX::generateSerialNumber()
@@ -267,15 +447,6 @@ OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
267 return(result); 447 return(result);
268} 448}
269 449
270OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
271{
272 OSErr result = noErr;
273
274 LLAppViewer::instance()->userQuit();
275
276 return(result);
277}
278
279OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata) 450OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata)
280{ 451{
281 OSStatus result = eventNotHandledErr; 452 OSStatus result = eventNotHandledErr;