aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llappviewerlinux.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llappviewerlinux.cpp307
1 files changed, 270 insertions, 37 deletions
diff --git a/linden/indra/newview/llappviewerlinux.cpp b/linden/indra/newview/llappviewerlinux.cpp
index 0a4a9cf..643013b 100644
--- a/linden/indra/newview/llappviewerlinux.cpp
+++ b/linden/indra/newview/llappviewerlinux.cpp
@@ -1,6 +1,6 @@
1/** 1/**
2 * @file llappviewerlinux.cpp 2 * @file llappviewerlinux.cpp
3 * @brief The LLAppViewerWin32 class definitions 3 * @brief The LLAppViewerLinux class definitions
4 * 4 *
5 * $LicenseInfo:firstyear=2007&license=viewergpl$ 5 * $LicenseInfo:firstyear=2007&license=viewergpl$
6 * 6 *
@@ -36,8 +36,10 @@
36#include "llcommandlineparser.h" 36#include "llcommandlineparser.h"
37 37
38#include "llmemtype.h" 38#include "llmemtype.h"
39#include "llurldispatcher.h" // SLURL from other app instance
39#include "llviewernetwork.h" 40#include "llviewernetwork.h"
40#include "llviewercontrol.h" 41#include "llviewercontrol.h"
42#include "llwindowsdl.h"
41#include "llmd5.h" 43#include "llmd5.h"
42#include "llfindlocale.h" 44#include "llfindlocale.h"
43 45
@@ -60,6 +62,17 @@
60# include "ELFIO/ELFIO.h" // for better backtraces 62# include "ELFIO/ELFIO.h" // for better backtraces
61#endif 63#endif
62 64
65#if LL_DBUS_ENABLED
66# include "llappviewerlinux_api_dbus.h"
67
68// regrettable hacks to give us better runtime compatibility with older systems inside llappviewerlinux_api.h:
69#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0)
70#undef g_return_if_fail
71#define g_return_if_fail(COND) llg_return_if_fail(COND)
72// The generated API
73# include "llappviewerlinux_api.h"
74#endif
75
63namespace 76namespace
64{ 77{
65 int gArgC = 0; 78 int gArgC = 0;
@@ -321,6 +334,193 @@ bool LLAppViewerLinux::init()
321 return LLAppViewer::init(); 334 return LLAppViewer::init();
322} 335}
323 336
337bool LLAppViewerLinux::restoreErrorTrap()
338{
339 // *NOTE:Mani there is a case for implementing this or the mac.
340 // Linux doesn't need it to my knowledge.
341 return true;
342}
343
344/////////////////////////////////////////
345#if LL_DBUS_ENABLED
346
347typedef struct
348{
349 GObjectClass parent_class;
350} ViewerAppAPIClass;
351
352static void viewerappapi_init(ViewerAppAPI *server);
353static void viewerappapi_class_init(ViewerAppAPIClass *klass);
354
355///
356
357// regrettable hacks to give us better runtime compatibility with older systems in general
358static GType llg_type_register_static_simple_ONCE(GType parent_type,
359 const gchar *type_name,
360 guint class_size,
361 GClassInitFunc class_init,
362 guint instance_size,
363 GInstanceInitFunc instance_init,
364 GTypeFlags flags)
365{
366 static GTypeInfo type_info;
367 memset(&type_info, 0, sizeof(type_info));
368
369 type_info.class_size = class_size;
370 type_info.class_init = class_init;
371 type_info.instance_size = instance_size;
372 type_info.instance_init = instance_init;
373
374 return g_type_register_static(parent_type, type_name, &type_info, flags);
375}
376#define llg_intern_static_string(S) (S)
377#define g_intern_static_string(S) llg_intern_static_string(S)
378#define g_type_register_static_simple(parent_type, type_name, class_size, class_init, instance_size, instance_init, flags) llg_type_register_static_simple_ONCE(parent_type, type_name, class_size, class_init, instance_size, instance_init, flags)
379
380G_DEFINE_TYPE(ViewerAppAPI, viewerappapi, G_TYPE_OBJECT);
381
382void viewerappapi_class_init(ViewerAppAPIClass *klass)
383{
384}
385
386static bool dbus_server_init = false;
387
388void viewerappapi_init(ViewerAppAPI *server)
389{
390 // Connect to the default DBUS, register our service/API.
391
392 if (!dbus_server_init)
393 {
394 GError *error = NULL;
395
396 server->connection = lldbus_g_bus_get(DBUS_BUS_SESSION, &error);
397 if (server->connection)
398 {
399 lldbus_g_object_type_install_info(viewerappapi_get_type(), &dbus_glib_viewerapp_object_info);
400
401 lldbus_g_connection_register_g_object(server->connection, VIEWERAPI_PATH, G_OBJECT(server));
402
403 DBusGProxy *serverproxy = lldbus_g_proxy_new_for_name(server->connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
404
405 guint request_name_ret_unused;
406 // akin to org_freedesktop_DBus_request_name
407 if (lldbus_g_proxy_call(serverproxy, "RequestName", &error, G_TYPE_STRING, VIEWERAPI_SERVICE, G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &request_name_ret_unused, G_TYPE_INVALID))
408 {
409 // total success.
410 dbus_server_init = true;
411 }
412 else
413 {
414 llwarns << "Unable to register service name: " << error->message << llendl;
415 }
416
417 g_object_unref(serverproxy);
418 }
419 else
420 {
421 g_warning("Unable to connect to dbus: %s", error->message);
422 }
423
424 if (error)
425 g_error_free(error);
426 }
427}
428
429gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **success_rtn, GError **error)
430{
431 bool success = false;
432
433 llinfos << "Was asked to go to slurl: " << slurl << llendl;
434
435 const bool from_external_browser = true;
436 if (LLURLDispatcher::dispatch(slurl, from_external_browser))
437 {
438 // bring window to foreground, as it has just been "launched" from a URL
439 // todo: hmm, how to get there from here?
440 //xxx->mWindow->bringToFront();
441 success = true;
442 }
443
444 *success_rtn = g_new (gboolean, 1);
445 (*success_rtn)[0] = (gboolean)success;
446
447 return TRUE; // the invokation succeeded, even if the actual dispatch didn't.
448}
449
450///
451
452//virtual
453bool LLAppViewerLinux::initSLURLHandler()
454{
455 if (!grab_dbus_syms(DBUSGLIB_DYLIB_DEFAULT_NAME))
456 {
457 return false; // failed
458 }
459
460 g_type_init();
461
462 //ViewerAppAPI *api_server = (ViewerAppAPI*)
463 g_object_new(viewerappapi_get_type(), NULL);
464
465 return true;
466}
467
468//virtual
469bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url)
470{
471 if (!grab_dbus_syms(DBUSGLIB_DYLIB_DEFAULT_NAME))
472 {
473 return false; // failed
474 }
475
476 bool success = false;
477 DBusGConnection *bus;
478 GError *error = NULL;
479
480 g_type_init();
481
482 bus = lldbus_g_bus_get (DBUS_BUS_SESSION, &error);
483 if (bus)
484 {
485 gboolean rtn = FALSE;
486 DBusGProxy *remote_object =
487 lldbus_g_proxy_new_for_name(bus, VIEWERAPI_SERVICE, VIEWERAPI_PATH, VIEWERAPI_INTERFACE);
488
489 if (lldbus_g_proxy_call(remote_object, "GoSLURL", &error,
490 G_TYPE_STRING, url.c_str(), G_TYPE_INVALID,
491 G_TYPE_BOOLEAN, &rtn, G_TYPE_INVALID))
492 {
493 success = rtn;
494 }
495 else
496 {
497 llinfos << "Call-out to other instance failed (perhaps not running): " << error->message << llendl;
498 }
499
500 g_object_unref(G_OBJECT(remote_object));
501 }
502 else
503 {
504 llwarns << "Couldn't connect to session bus: " << error->message << llendl;
505 }
506
507 if (error)
508 g_error_free(error);
509
510 return success;
511}
512
513#else // LL_DBUS_ENABLED
514bool LLAppViewerLinux::initSLURLHandler()
515{
516 return false; // not implemented without dbus
517}
518bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url)
519{
520 return false; // not implemented without dbus
521}
522#endif // LL_DBUS_ENABLED
523
324void LLAppViewerLinux::handleSyncCrashTrace() 524void LLAppViewerLinux::handleSyncCrashTrace()
325{ 525{
326 // This backtrace writes into stack_trace.log 526 // This backtrace writes into stack_trace.log
@@ -331,57 +531,90 @@ void LLAppViewerLinux::handleSyncCrashTrace()
331# endif // LL_ELFBIN 531# endif // LL_ELFBIN
332} 532}
333 533
334void LLAppViewerLinux::handleCrashReporting() 534void LLAppViewerLinux::handleCrashReporting(bool reportFreeze)
335{ 535{
336 const S32 cb = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING); 536 std::string cmd =gDirUtilp->getAppRODataDir();
337 537 cmd += gDirUtilp->getDirDelimiter();
338 // Always generate the report, have the logger do the asking, and 538#if LL_LINUX
339 // don't wait for the logger before exiting (-> total cleanup). 539 cmd += "linux-crash-logger.bin";
340 if (CRASH_BEHAVIOR_NEVER_SEND != cb) 540#else // LL_SOLARIS
341 { 541 cmd += "bin/solaris-crash-logger";
342 // launch the actual crash logger 542#endif // LL_LINUX
343 const char* ask_dialog = "-dialog"; 543
344 if (CRASH_BEHAVIOR_ASK != cb) 544 if(reportFreeze)
345 ask_dialog = ""; // omit '-dialog' option 545 {
346 std::string cmd =gDirUtilp->getAppRODataDir(); 546 char* const cmdargv[] =
347 cmd += gDirUtilp->getDirDelimiter(); 547 {(char*)cmd.c_str(),
348 cmd += "linux-crash-logger.bin"; 548 (char*)"-previous",
349 const char * cmdargv[] =
350 {cmd.c_str(),
351 ask_dialog,
352 "-user",
353 (char*)LLViewerLogin::getInstance()->getGridLabel().c_str(),
354 "-name",
355 LLAppViewer::instance()->getSecondLifeTitle().c_str(),
356 NULL}; 549 NULL};
357 fflush(NULL); 550
551 fflush(NULL); // flush all buffers before the child inherits them
358 pid_t pid = fork(); 552 pid_t pid = fork();
359 if (pid == 0) 553 if (pid == 0)
360 { // child 554 { // child
361 execv(cmd.c_str(), (char* const*) cmdargv); /* Flawfinder: ignore */ 555 execv(cmd.c_str(), cmdargv); /* Flawfinder: Ignore */
362 llwarns << "execv failure when trying to start " << cmd << llendl; 556 llwarns << "execv failure when trying to start " << cmd << llendl;
363 _exit(1); // avoid atexit() 557 _exit(1); // avoid atexit()
364 } 558 } else {
365 else
366 {
367 if (pid > 0) 559 if (pid > 0)
368 { 560 {
369 // DO NOT wait for child proc to die; we want 561 // wait for child proc to die
370 // the logger to outlive us while we quit to 562 int childExitStatus;
371 // free up the screen/keyboard/etc. 563 waitpid(pid, &childExitStatus, 0);
372 ////int childExitStatus; 564 } else {
373 ////waitpid(pid, &childExitStatus, 0); 565 llwarns << "fork failure." << llendl;
566 }
567 }
568 }
569 else
570 {
571 const S32 cb = gCrashSettings.getS32(CRASH_BEHAVIOR_SETTING);
572
573 // Always generate the report, have the logger do the asking, and
574 // don't wait for the logger before exiting (-> total cleanup).
575 if (CRASH_BEHAVIOR_NEVER_SEND != cb)
576 {
577 // launch the actual crash logger
578 const char* ask_dialog = "-dialog";
579 if (CRASH_BEHAVIOR_ASK != cb)
580 ask_dialog = ""; // omit '-dialog' option
581 const char * cmdargv[] =
582 {cmd.c_str(),
583 ask_dialog,
584 "-user",
585 (char*)LLViewerLogin::getInstance()->getGridLabel().c_str(),
586 "-name",
587 LLAppViewer::instance()->getSecondLifeTitle().c_str(),
588 NULL};
589 fflush(NULL);
590 pid_t pid = fork();
591 if (pid == 0)
592 { // child
593 execv(cmd.c_str(), (char* const*) cmdargv); /* Flawfinder: ignore */
594 llwarns << "execv failure when trying to start " << cmd << llendl;
595 _exit(1); // avoid atexit()
374 } 596 }
375 else 597 else
376 { 598 {
377 llwarns << "fork failure." << llendl; 599 if (pid > 0)
600 {
601 // DO NOT wait for child proc to die; we want
602 // the logger to outlive us while we quit to
603 // free up the screen/keyboard/etc.
604 ////int childExitStatus;
605 ////waitpid(pid, &childExitStatus, 0);
606 }
607 else
608 {
609 llwarns << "fork failure." << llendl;
610 }
378 } 611 }
379 } 612 }
613 // Sometimes signals don't seem to quit the viewer. Also, we may
614 // have been called explicitly instead of from a signal handler.
615 // Make sure we exit so as to not totally confuse the user.
616 _exit(1); // avoid atexit(), else we may re-crash in dtors.
380 } 617 }
381 // Sometimes signals don't seem to quit the viewer. Also, we may
382 // have been called explicitly instead of from a signal handler.
383 // Make sure we exit so as to not totally confuse the user.
384 _exit(1); // avoid atexit(), else we may re-crash in dtors.
385} 618}
386 619
387bool LLAppViewerLinux::beingDebugged() 620bool LLAppViewerLinux::beingDebugged()