From 464a0df4c1d3e4073fe0bde506ac1d4aa194b02f Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 30 Jun 2016 16:51:50 -0400 Subject: DRTVWR-418: Unify control flow through LLAppViewer across platforms. The LLApp API used to consist of init(), mainLoop(), cleanup() methods. This makes sense -- but on Mac that structure was being subverted. The method called mainLoop() was in fact being called once per frame. There was initialization code in the method, which (on Mac) needed to be skipped with an already-initialized bool. There was a 'while' loop which (on Mac) needed to be turned into an 'if' instead so the method would return after every frame. Rename LLApp::mainLoop() to frame(). Propagate through subclasses LLAppViewer and LLCrashLogger. Document the fact that frame() returns true to mean "done." (This was always the case, but had to be inferred from the code.) Rename the Mac Objective-C function mainLoop to oneFrame. Rename the C++ free function it calls from runMainLoop() to pumpMainLoop(). Add comments to llappdelegate-objc.mm explaining (inferred) control flow. Change the Linux viewer main() and the Windows viewer WINMAIN() from a single LLAppViewer::mainLoop() call to repeatedly call frame() until it returns true. Move initialization code from the top of LLAppViewer::frame() to the init() method, where it more properly belongs. Remove corresponding mMainLoopInitialized flag (and all references) from LLAppViewer. Remove 'while (! LLApp::isExiting())' (or on Mac, 'if (! LLApp::isExiting())') from LLAppViewer::frame() -- thus unindenting the whole body of the 'while' and causing many lines of apparent change. (Apologies to reviewers.) There are four LLApp states: APP_STATUS_RUNNING, APP_STATUS_QUITTING, APP_STATUS_STOPPED and APP_STATUS_ERROR. Change LLAppViewer::frame() return value from (isExiting()) (QUITTING or ERROR) to (! isRunning()). I do not know under what circumstances the state might transition to STOPPED during a frame() call, but I'm quite sure that if it does, we don't want to call frame() again. We only want a subsequent call if the state is RUNNING. Also rename mainLoop() method in LLCrashLogger subclasses LLCrashLoggerWindows, LLCrashLoggerMac, LLCrashLoggerLinux. Of course it's completely up to the frame() method whether to yield control; none of those in fact do. Honor protocol by returning true (frame() is done), even though each one's main() caller ignores the return value. In fact LLCrashLoggerWindows::mainLoop() wasn't using the return protocol correctly anyway, returning wParam or 0 or 1 -- possibly because the return protocol was never explicitly documented. It should always return true: "I'm done, don't call me again." --- indra/linux_crash_logger/linux_crash_logger.cpp | 2 +- indra/linux_crash_logger/llcrashloggerlinux.cpp | 2 +- indra/linux_crash_logger/llcrashloggerlinux.h | 2 +- indra/llcommon/llapp.h | 8 +- indra/llcrashlogger/llcrashlogger.h | 2 +- indra/llwindow/llappdelegate-objc.h | 2 +- indra/llwindow/llwindowmacosx-objc.h | 2 +- indra/mac_crash_logger/llcrashloggermac.cpp | 2 +- indra/mac_crash_logger/llcrashloggermac.h | 2 +- indra/mac_crash_logger/mac_crash_logger.cpp | 2 +- indra/newview/llappdelegate-objc.mm | 24 +- indra/newview/llappviewer.cpp | 456 +++++++++++------------- indra/newview/llappviewer.h | 3 +- indra/newview/llappviewerlinux.cpp | 6 +- indra/newview/llappviewermacosx.cpp | 9 +- indra/newview/llappviewerwin32.cpp | 6 +- indra/test/llapp_tut.cpp | 2 +- indra/win_crash_logger/llcrashloggerwindows.cpp | 8 +- indra/win_crash_logger/llcrashloggerwindows.h | 2 +- indra/win_crash_logger/win_crash_logger.cpp | 2 +- 20 files changed, 263 insertions(+), 281 deletions(-) (limited to 'indra') diff --git a/indra/linux_crash_logger/linux_crash_logger.cpp b/indra/linux_crash_logger/linux_crash_logger.cpp index 9d5ec33fed..63e5409876 100644 --- a/indra/linux_crash_logger/linux_crash_logger.cpp +++ b/indra/linux_crash_logger/linux_crash_logger.cpp @@ -51,7 +51,7 @@ int main(int argc, char **argv) return 1; } - app.mainLoop(); + app.frame(); app.cleanup(); LL_INFOS() << "Crash reporter finished normally." << LL_ENDL; return 0; diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp index e2d2e7ff26..4092d43fc5 100644 --- a/indra/linux_crash_logger/llcrashloggerlinux.cpp +++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp @@ -114,7 +114,7 @@ void LLCrashLoggerLinux::gatherPlatformSpecificFiles() { } -bool LLCrashLoggerLinux::mainLoop() +bool LLCrashLoggerLinux::frame() { bool send_logs = true; if(CRASH_BEHAVIOR_ASK == getCrashBehavior()) diff --git a/indra/linux_crash_logger/llcrashloggerlinux.h b/indra/linux_crash_logger/llcrashloggerlinux.h index dae6c46651..789f6f03f5 100644 --- a/indra/linux_crash_logger/llcrashloggerlinux.h +++ b/indra/linux_crash_logger/llcrashloggerlinux.h @@ -36,7 +36,7 @@ class LLCrashLoggerLinux : public LLCrashLogger public: LLCrashLoggerLinux(void); ~LLCrashLoggerLinux(void); - virtual bool mainLoop(); + virtual bool frame(); virtual void updateApplication(const std::string& = LLStringUtil::null); virtual void gatherPlatformSpecificFiles(); virtual bool cleanup(); diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index d9933b3d36..ff9a92b45f 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -172,12 +172,12 @@ public: virtual bool cleanup() = 0; // Override to do application cleanup // - // mainLoop() + // frame() // - // Runs the application main loop. It's assumed that when you exit - // this method, the application is in one of the cleanup states, either QUITTING or ERROR + // Pass control to the application for a single frame. Returns 'done' + // flag: if frame() returns false, it expects to be called again. // - virtual bool mainLoop() = 0; // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit. + virtual bool frame() = 0; // Override for application body logic // // Crash logging diff --git a/indra/llcrashlogger/llcrashlogger.h b/indra/llcrashlogger/llcrashlogger.h index 8b4afae24a..56e26c23ba 100644 --- a/indra/llcrashlogger/llcrashlogger.h +++ b/indra/llcrashlogger/llcrashlogger.h @@ -57,7 +57,7 @@ public: LLSD constructPostData(); virtual void updateApplication(const std::string& message = LLStringUtil::null); virtual bool init(); - virtual bool mainLoop() = 0; + virtual bool frame() = 0; virtual bool cleanup() = 0; void commonCleanup(); void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; } diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h index faa5d3abb7..6daf1ac55b 100644 --- a/indra/llwindow/llappdelegate-objc.h +++ b/indra/llwindow/llappdelegate-objc.h @@ -41,7 +41,7 @@ @property (retain) NSString *currentInputLanguage; -- (void) mainLoop; +- (void) oneFrame; - (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent; - (void) languageUpdated; - (bool) romanScript; diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index c22f3382fb..b06cd2c184 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -69,7 +69,7 @@ typedef const NativeKeyEventData * NSKeyEventRef; // These are defined in llappviewermacosx.cpp. bool initViewer(); void handleQuit(); -bool runMainLoop(); +bool pumpMainLoop(); void initMainLoop(); void cleanupViewer(); void handleUrl(const char* url); diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp index 3149fad6e8..ec3616e26a 100644 --- a/indra/mac_crash_logger/llcrashloggermac.cpp +++ b/indra/mac_crash_logger/llcrashloggermac.cpp @@ -64,7 +64,7 @@ void LLCrashLoggerMac::gatherPlatformSpecificFiles() { } -bool LLCrashLoggerMac::mainLoop() +bool LLCrashLoggerMac::frame() { if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND) diff --git a/indra/mac_crash_logger/llcrashloggermac.h b/indra/mac_crash_logger/llcrashloggermac.h index 6d8f63ecac..05ef8c9f53 100644 --- a/indra/mac_crash_logger/llcrashloggermac.h +++ b/indra/mac_crash_logger/llcrashloggermac.h @@ -37,7 +37,7 @@ public: LLCrashLoggerMac(void); ~LLCrashLoggerMac(void); virtual bool init(); - virtual bool mainLoop(); + virtual bool frame(); virtual bool cleanup(); virtual void gatherPlatformSpecificFiles(); }; diff --git a/indra/mac_crash_logger/mac_crash_logger.cpp b/indra/mac_crash_logger/mac_crash_logger.cpp index 95d4e65207..54e41a1954 100644 --- a/indra/mac_crash_logger/mac_crash_logger.cpp +++ b/indra/mac_crash_logger/mac_crash_logger.cpp @@ -49,7 +49,7 @@ int main(int argc, char **argv) { // return NSApplicationMain(argc, (const char **)argv); } - app.mainLoop(); + app.frame(); app.cleanup(); LL_INFOS() << "Crash reporter finished normally." << LL_ENDL; diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 549df80fa1..be8877328d 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -48,16 +48,19 @@ - (void) applicationDidFinishLaunching:(NSNotification *)notification { frameTimer = nil; - + [self languageUpdated]; - + if (initViewer()) { - frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES]; + // Set up recurring calls to oneFrame (repeating timer with timeout 0) + // until applicationShouldTerminate. + frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self + selector:@selector(oneFrame) userInfo:nil repeats:YES]; } else { handleQuit(); } - + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil]; // [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL]; @@ -96,22 +99,29 @@ - (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender { - if (!runMainLoop()) + // run one frame to assess state + if (!pumpMainLoop()) { + // pumpMainLoop() returns true when done, false if it wants to be + // called again. Since it returned false, do not yet cancel + // frameTimer. handleQuit(); return NSTerminateCancel; } else { + // pumpMainLoop() returned true: it's done. Okay, done with frameTimer. [frameTimer release]; cleanupViewer(); return NSTerminateNow; } } -- (void) mainLoop +- (void) oneFrame { - bool appExiting = runMainLoop(); + bool appExiting = pumpMainLoop(); if (appExiting) { + // Once pumpMainLoop() reports that we're done, cancel frameTimer: + // stop the repetitive calls. [frameTimer release]; [[NSApplication sharedApplication] terminate:self]; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b6d02ea2f8..604e45f314 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -769,9 +769,6 @@ bool LLAppViewer::init() // // Start of the application // -#ifdef LL_DARWIN - mMainLoopInitialized = false; -#endif // initialize LLWearableType translation bridge. // Memory will be cleaned up in ::cleanupClass() @@ -1220,6 +1217,23 @@ bool LLAppViewer::init() boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1), boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS)); + /*----------------------------------------------------------------------*/ + // nat 2016-06-29 moved the following here from the former mainLoop(). + mMainloopTimeout = new LLWatchdogTimeout(); + + // Create IO Pump to use for HTTP Requests. + gServicePump = new LLPumpIO(gAPRPoolp); + + // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. + + LLVoiceChannel::initClass(); + LLVoiceClient::getInstance()->init(gServicePump); + LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true); + + joystick = LLViewerJoystick::getInstance(); + joystick->setNeedsReset(true); + /*----------------------------------------------------------------------*/ + return true; } @@ -1294,297 +1308,255 @@ static LLTrace::BlockTimerStatHandle FTM_AGENT_UPDATE("Update"); // externally visible timers LLTrace::BlockTimerStatHandle FTM_FRAME("Frame"); -bool LLAppViewer::mainLoop() +bool LLAppViewer::frame() { -#ifdef LL_DARWIN - if (!mMainLoopInitialized) -#endif - { - LL_INFOS() << "Entering main_loop" << LL_ENDL; - mMainloopTimeout = new LLWatchdogTimeout(); - - //------------------------------------------- - // Run main loop until time to quit - //------------------------------------------- - - // Create IO Pump to use for HTTP Requests. - gServicePump = new LLPumpIO(gAPRPoolp); - - // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. - - LLVoiceChannel::initClass(); - LLVoiceClient::getInstance()->init(gServicePump); - LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true); - - joystick = LLViewerJoystick::getInstance(); - joystick->setNeedsReset(true); - -#ifdef LL_DARWIN - // Ensure that this section of code never gets called again on OS X. - mMainLoopInitialized = true; -#endif - } - // As we do not (yet) send data on the mainloop LLEventPump that varies - // with each frame, no need to instantiate a new LLSD event object each - // time. Obviously, if that changes, just instantiate the LLSD at the - // point of posting. - LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); - - LLSD newFrame; - + LLSD newFrame; + LLTimer frameTimer,idleTimer; LLTimer debugTime; - + //LLPrivateMemoryPoolTester::getInstance()->run(false) ; //LLPrivateMemoryPoolTester::getInstance()->run(true) ; //LLPrivateMemoryPoolTester::destroy() ; - // Handle messages -#ifdef LL_DARWIN - if (!LLApp::isExiting()) -#else - while (!LLApp::isExiting()) -#endif + LL_RECORD_BLOCK_TIME(FTM_FRAME); + LLTrace::BlockTimer::processTimes(); + LLTrace::get_frame_recording().nextPeriod(); + LLTrace::BlockTimer::logStats(); + + LLTrace::get_thread_recorder()->pullFromChildren(); + + //clear call stack records + LL_CLEAR_CALLSTACKS(); + + //check memory availability information + checkMemory() ; + + try { - LL_RECORD_BLOCK_TIME(FTM_FRAME); - LLTrace::BlockTimer::processTimes(); - LLTrace::get_frame_recording().nextPeriod(); - LLTrace::BlockTimer::logStats(); + pingMainloopTimeout("Main:MiscNativeWindowEvents"); + + if (gViewerWindow) + { + LL_RECORD_BLOCK_TIME(FTM_MESSAGES); + gViewerWindow->getWindow()->processMiscNativeEvents(); + } - LLTrace::get_thread_recorder()->pullFromChildren(); + pingMainloopTimeout("Main:GatherInput"); - //clear call stack records - LL_CLEAR_CALLSTACKS(); + if (gViewerWindow) + { + LL_RECORD_BLOCK_TIME(FTM_MESSAGES); + if (!restoreErrorTrap()) + { + LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL; + } - //check memory availability information - checkMemory() ; + gViewerWindow->getWindow()->gatherInput(); + } + +#if 1 && !LL_RELEASE_FOR_DOWNLOAD + // once per second debug info + if (debugTime.getElapsedTimeF32() > 1.f) + { + debugTime.reset(); + } - try +#endif + //memory leaking simulation + LLFloaterMemLeak* mem_leak_instance = + LLFloaterReg::findTypedInstance("mem_leaking"); + if(mem_leak_instance) { - pingMainloopTimeout("Main:MiscNativeWindowEvents"); + mem_leak_instance->idle() ; + } + + // canonical per-frame event + mainloop.post(newFrame); - if (gViewerWindow) + if (!LLApp::isExiting()) + { + pingMainloopTimeout("Main:JoystickKeyboard"); + + // Scan keyboard for movement keys. Command keys and typing + // are handled by windows callbacks. Don't do this until we're + // done initializing. JC + if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible()) + && gViewerWindow->getActive() + && !gViewerWindow->getWindow()->getMinimized() + && LLStartUp::getStartupState() == STATE_STARTED + && (gHeadlessClient || !gViewerWindow->getShowProgress()) + && !gFocusMgr.focusLocked()) { - LL_RECORD_BLOCK_TIME(FTM_MESSAGES); - gViewerWindow->getWindow()->processMiscNativeEvents(); + joystick->scanJoystick(); + gKeyboard->scanKeyboard(); } - - pingMainloopTimeout("Main:GatherInput"); - - if (gViewerWindow) + + // Update state based on messages, user input, object idle. { - LL_RECORD_BLOCK_TIME(FTM_MESSAGES); - if (!restoreErrorTrap()) - { - LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL; - } + pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! + + LL_RECORD_BLOCK_TIME(FTM_IDLE); + idle(); - gViewerWindow->getWindow()->gatherInput(); + resumeMainloopTimeout(); } -#if 1 && !LL_RELEASE_FOR_DOWNLOAD - // once per second debug info - if (debugTime.getElapsedTimeF32() > 1.f) + if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED)) { - debugTime.reset(); + pauseMainloopTimeout(); + saveFinalSnapshot(); + disconnectViewer(); + resumeMainloopTimeout(); } - -#endif - //memory leaking simulation - LLFloaterMemLeak* mem_leak_instance = - LLFloaterReg::findTypedInstance("mem_leaking"); - if(mem_leak_instance) - { - mem_leak_instance->idle() ; - } - - // canonical per-frame event - mainloop.post(newFrame); - if (!LLApp::isExiting()) + // Render scene. + // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18 + if (!LLApp::isExiting() && !gHeadlessClient) { - pingMainloopTimeout("Main:JoystickKeyboard"); - - // Scan keyboard for movement keys. Command keys and typing - // are handled by windows callbacks. Don't do this until we're - // done initializing. JC - if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible()) - && gViewerWindow->getActive() - && !gViewerWindow->getWindow()->getMinimized() - && LLStartUp::getStartupState() == STATE_STARTED - && (gHeadlessClient || !gViewerWindow->getShowProgress()) - && !gFocusMgr.focusLocked()) - { - joystick->scanJoystick(); - gKeyboard->scanKeyboard(); - } + pingMainloopTimeout("Main:Display"); + gGLActive = TRUE; + display(); + pingMainloopTimeout("Main:Snapshot"); + LLFloaterSnapshot::update(); // take snapshots + gGLActive = FALSE; + } + } - // Update state based on messages, user input, object idle. - { - pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! - - LL_RECORD_BLOCK_TIME(FTM_IDLE); - idle(); + pingMainloopTimeout("Main:Sleep"); - resumeMainloopTimeout(); - } - - if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED)) - { - pauseMainloopTimeout(); - saveFinalSnapshot(); - disconnectViewer(); - resumeMainloopTimeout(); - } + pauseMainloopTimeout(); - // Render scene. - // *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18 - if (!LLApp::isExiting() && !gHeadlessClient) + // Sleep and run background threads + { + LL_RECORD_BLOCK_TIME(FTM_SLEEP); + + // yield some time to the os based on command line option + if(mYieldTime >= 0) + { + LL_RECORD_BLOCK_TIME(FTM_YIELD); + ms_sleep(mYieldTime); + } + + // yield cooperatively when not running as foreground window + if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible()) + || !gFocusMgr.getAppHasFocus()) + { + // Sleep if we're not rendering, or the window is minimized. + S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000); + // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads + // of equal priority on Windows + if (milliseconds_to_sleep > 0) { - pingMainloopTimeout("Main:Display"); - gGLActive = TRUE; - display(); - pingMainloopTimeout("Main:Snapshot"); - LLFloaterSnapshot::update(); // take snapshots - gGLActive = FALSE; + ms_sleep(milliseconds_to_sleep); + // also pause worker threads during this wait period + LLAppViewer::getTextureCache()->pause(); + LLAppViewer::getImageDecodeThread()->pause(); } } - - pingMainloopTimeout("Main:Sleep"); - pauseMainloopTimeout(); + if (mRandomizeFramerate) + { + ms_sleep(rand() % 200); + } - // Sleep and run background threads + if (mPeriodicSlowFrame + && (gFrameCount % 10 == 0)) { - LL_RECORD_BLOCK_TIME(FTM_SLEEP); - - // yield some time to the os based on command line option - if(mYieldTime >= 0) - { - LL_RECORD_BLOCK_TIME(FTM_YIELD); - ms_sleep(mYieldTime); - } + LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL; + ms_sleep(500); + } + + const F64Milliseconds max_idle_time = llmin(.005f*10.f*(F32Milliseconds)gFrameTimeSeconds, F32Milliseconds(5)); // 5 ms a second + idleTimer.reset(); + S32 total_work_pending = 0; + S32 total_io_pending = 0; + while(1) + { + S32 work_pending = 0; + S32 io_pending = 0; + F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f); + + work_pending += updateTextureThreads(max_time); - // yield cooperatively when not running as foreground window - if ( (gViewerWindow && !gViewerWindow->getWindow()->getVisible()) - || !gFocusMgr.getAppHasFocus()) { - // Sleep if we're not rendering, or the window is minimized. - S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000); - // don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads - // of equal priority on Windows - if (milliseconds_to_sleep > 0) - { - ms_sleep(milliseconds_to_sleep); - // also pause worker threads during this wait period - LLAppViewer::getTextureCache()->pause(); - LLAppViewer::getImageDecodeThread()->pause(); - } + LL_RECORD_BLOCK_TIME(FTM_VFS); + io_pending += LLVFSThread::updateClass(1); } - - if (mRandomizeFramerate) { - ms_sleep(rand() % 200); + LL_RECORD_BLOCK_TIME(FTM_LFS); + io_pending += LLLFSThread::updateClass(1); } - if (mPeriodicSlowFrame - && (gFrameCount % 10 == 0)) + if (io_pending > 1000) { - LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL; - ms_sleep(500); + ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up } - const F64Milliseconds max_idle_time = llmin(.005f*10.f*(F32Milliseconds)gFrameTimeSeconds, F32Milliseconds(5)); // 5 ms a second - idleTimer.reset(); - S32 total_work_pending = 0; - S32 total_io_pending = 0; - while(1) - { - S32 work_pending = 0; - S32 io_pending = 0; - F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f); - - work_pending += updateTextureThreads(max_time); - - { - LL_RECORD_BLOCK_TIME(FTM_VFS); - io_pending += LLVFSThread::updateClass(1); - } - { - LL_RECORD_BLOCK_TIME(FTM_LFS); - io_pending += LLLFSThread::updateClass(1); - } - - if (io_pending > 1000) - { - ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up - } - - total_work_pending += work_pending ; - total_io_pending += io_pending ; - - if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time) - { - break; - } - } - gMeshRepo.update() ; + total_work_pending += work_pending ; + total_io_pending += io_pending ; - if(!total_work_pending) //pause texture fetching threads if nothing to process. + if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time) { - LLAppViewer::getTextureCache()->pause(); - LLAppViewer::getImageDecodeThread()->pause(); - LLAppViewer::getTextureFetch()->pause(); - } - if(!total_io_pending) //pause file threads if nothing to process. - { - LLVFSThread::sLocal->pause(); - LLLFSThread::sLocal->pause(); - } - - //texture fetching debugger - if(LLTextureFetchDebugger::isEnabled()) - { - LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance = - LLFloaterReg::findTypedInstance("tex_fetch_debugger"); - if(tex_fetch_debugger_instance) - { - tex_fetch_debugger_instance->idle() ; - } + break; } + } + gMeshRepo.update() ; + + if(!total_work_pending) //pause texture fetching threads if nothing to process. + { + LLAppViewer::getTextureCache()->pause(); + LLAppViewer::getImageDecodeThread()->pause(); + LLAppViewer::getTextureFetch()->pause(); + } + if(!total_io_pending) //pause file threads if nothing to process. + { + LLVFSThread::sLocal->pause(); + LLLFSThread::sLocal->pause(); + } - if ((LLStartUp::getStartupState() >= STATE_CLEANUP) && - (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD)) + //texture fetching debugger + if(LLTextureFetchDebugger::isEnabled()) + { + LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance = + LLFloaterReg::findTypedInstance("tex_fetch_debugger"); + if(tex_fetch_debugger_instance) { - gFrameStalls++; + tex_fetch_debugger_instance->idle() ; } - frameTimer.reset(); - - resumeMainloopTimeout(); - - pingMainloopTimeout("Main:End"); - } - } - catch(std::bad_alloc) - { - LLMemory::logMemoryInfo(TRUE) ; + } - //stop memory leaking simulation - LLFloaterMemLeak* mem_leak_instance = - LLFloaterReg::findTypedInstance("mem_leaking"); - if(mem_leak_instance) + if ((LLStartUp::getStartupState() >= STATE_CLEANUP) && + (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD)) { - mem_leak_instance->stop() ; - LL_WARNS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ; + gFrameStalls++; } - else - { - //output possible call stacks to log file. - LLError::LLCallStacks::print() ; + frameTimer.reset(); - LL_ERRS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ; - } + resumeMainloopTimeout(); + + pingMainloopTimeout("Main:End"); + } + } + catch(std::bad_alloc) + { + LLMemory::logMemoryInfo(TRUE) ; + + //stop memory leaking simulation + LLFloaterMemLeak* mem_leak_instance = + LLFloaterReg::findTypedInstance("mem_leaking"); + if(mem_leak_instance) + { + mem_leak_instance->stop() ; + LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ; + } + else + { + //output possible call stacks to log file. + LLError::LLCallStacks::print() ; + + LL_ERRS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ; } } @@ -1618,7 +1590,7 @@ bool LLAppViewer::mainLoop() LL_INFOS() << "Exiting main_loop" << LL_ENDL; } - return LLApp::isExiting(); + return ! LLApp::isRunning(); } S32 LLAppViewer::updateTextureThreads(F32 max_time) diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index b5e674bd7b..f7c1bb58b4 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -79,7 +79,7 @@ public: // virtual bool init(); // Override to do application initialization virtual bool cleanup(); // Override to do application cleanup - virtual bool mainLoop(); // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit. + virtual bool frame(); // Override for application body logic // Application control void flushVFSIO(); // waits for vfs transfers to complete @@ -283,7 +283,6 @@ private: std::string mSerialNumber; bool mPurgeCache; bool mPurgeOnExit; - bool mMainLoopInitialized; LLViewerJoystick* joystick; bool mSavedFinalSnapshot; diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index f5742b29cf..6f32aab851 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -95,10 +95,8 @@ int main( int argc, char **argv ) } // Run the application main loop - if(!LLApp::isQuitting()) - { - viewer_app_ptr->mainLoop(); - } + while (! viewer_app_ptr->frame()) + {} if (!LLApp::isError()) { diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index ca219fda59..4fe1e31668 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -117,12 +117,17 @@ void handleQuit() LLAppViewer::instance()->userQuit(); } -bool runMainLoop() +// This function is called pumpMainLoop() rather than runMainLoop() because +// it passes control to the viewer's main-loop logic for a single frame. Like +// LLAppViewer::frame(), it returns 'true' when it's done. Until then, it +// expects to be called again by the timer in LLAppDelegate +// (llappdelegate-objc.mm). +bool pumpMainLoop() { bool ret = LLApp::isQuitting(); if (!ret && gViewerAppPtr != NULL) { - ret = gViewerAppPtr->mainLoop(); + ret = gViewerAppPtr->frame(); } else { ret = true; } diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 4786f83bfd..a7f248ab5a 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -317,10 +317,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, } // Run the application main loop - if(!LLApp::isQuitting()) - { - viewer_app_ptr->mainLoop(); - } + while (! viewer_app_ptr->frame()) + {} if (!LLApp::isError()) { diff --git a/indra/test/llapp_tut.cpp b/indra/test/llapp_tut.cpp index aa5c0672e6..98e714a497 100644 --- a/indra/test/llapp_tut.cpp +++ b/indra/test/llapp_tut.cpp @@ -41,7 +41,7 @@ namespace tut public: virtual bool init() { return true; } virtual bool cleanup() { return true; } - virtual bool mainLoop() { return true; } + virtual bool frame() { return true; } }; LLTestApp* mApp; application() diff --git a/indra/win_crash_logger/llcrashloggerwindows.cpp b/indra/win_crash_logger/llcrashloggerwindows.cpp index 23c29e6b18..167acf6ac7 100644 --- a/indra/win_crash_logger/llcrashloggerwindows.cpp +++ b/indra/win_crash_logger/llcrashloggerwindows.cpp @@ -454,7 +454,7 @@ void LLCrashLoggerWindows::gatherPlatformSpecificFiles() //mDebugLog["DisplayDeviceInfo"] = gDXHardware.getDisplayInfo(); //Not initialized. } -bool LLCrashLoggerWindows::mainLoop() +bool LLCrashLoggerWindows::frame() { LL_INFOS() << "CrashSubmitBehavior is " << mCrashBehavior << LL_ENDL; @@ -503,14 +503,14 @@ bool LLCrashLoggerWindows::mainLoop() TranslateMessage(&msg); DispatchMessage(&msg); } - return msg.wParam; + return true; // msg.wParam; } else { LL_WARNS() << "Unknown crash behavior " << mCrashBehavior << LL_ENDL; - return 1; + return true; // 1; } - return 0; + return true; // 0; } void LLCrashLoggerWindows::updateApplication(const std::string& message) diff --git a/indra/win_crash_logger/llcrashloggerwindows.h b/indra/win_crash_logger/llcrashloggerwindows.h index 1812e2737e..f89b8708dc 100644 --- a/indra/win_crash_logger/llcrashloggerwindows.h +++ b/indra/win_crash_logger/llcrashloggerwindows.h @@ -46,7 +46,7 @@ public: static LLCrashLoggerWindows* sInstance; virtual bool init(); - virtual bool mainLoop(); + virtual bool frame(); virtual void updateApplication(const std::string& message = LLStringUtil::null); virtual bool cleanup(); virtual void gatherPlatformSpecificFiles(); diff --git a/indra/win_crash_logger/win_crash_logger.cpp b/indra/win_crash_logger/win_crash_logger.cpp index 366edd894b..7466dbb766 100644 --- a/indra/win_crash_logger/win_crash_logger.cpp +++ b/indra/win_crash_logger/win_crash_logger.cpp @@ -52,7 +52,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, } app.processingLoop(); - app.mainLoop(); + app.frame(); app.cleanup(); LL_INFOS() << "Crash reporter finished normally." << LL_ENDL; return 0; -- cgit v1.2.3 From b031b1a6255af0813698bd40586f30f7b0a76f58 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 13 Jul 2016 10:43:36 -0400 Subject: MAINT-5011: Derive remaining exception classes from std::exception. In particular: NotImplemented in llhttpnode.cpp RelocateError in llupdateinstaller.cpp LLProtectedDataException, LLCertException and subclasses in llsecapi.h Had to add no-throw destructor overrides to LLCertException and subclasses because otherwise clang complains that the implicitly-generated destructor's exception specification is more lax than the base class's. --- indra/llmessage/llhttpnode.cpp | 4 ++- indra/newview/llsecapi.cpp | 2 +- indra/newview/llsecapi.h | 34 ++++++++++++---------- .../updater/llupdateinstaller.cpp | 10 ++++--- 4 files changed, 29 insertions(+), 21 deletions(-) (limited to 'indra') diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp index f235965879..08688ca48b 100644 --- a/indra/llmessage/llhttpnode.cpp +++ b/indra/llmessage/llhttpnode.cpp @@ -31,6 +31,7 @@ #include "llstl.h" #include "llhttpconstants.h" +#include const std::string CONTEXT_HEADERS("headers"); const std::string CONTEXT_PATH("path"); @@ -92,8 +93,9 @@ LLHTTPNode::~LLHTTPNode() namespace { - class NotImplemented + struct NotImplemented: public std::runtime_error { + NotImplemented(): std::runtime_error("LLHTTPNode::NotImplemented") {} }; } diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index 4f9f83b6f2..c27709a57b 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -69,7 +69,7 @@ void initializeSecHandler() } if (!exception_msg.empty()) // an exception was thrown. { - throw LLProtectedDataException(exception_msg.c_str()); + throw LLProtectedDataException(exception_msg); } } diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 6fe3ee31cf..02438f77b7 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -32,6 +32,7 @@ #include #include #include "llpointer.h" +#include #ifdef LL_WINDOWS #pragma warning(disable:4250) @@ -116,17 +117,14 @@ -class LLProtectedDataException +struct LLProtectedDataException: public std::runtime_error { -public: - LLProtectedDataException(const char *msg) + LLProtectedDataException(const std::string& msg): + std::runtime_error(msg) { - LL_WARNS("SECAPI") << "Protected Data Error: " << (std::string)msg << LL_ENDL; - mMsg = (std::string)msg; + LL_WARNS("SECAPI") << "Protected Data Error: " << msg << LL_ENDL; } - std::string getMessage() { return mMsg; } -protected: - std::string mMsg; + std::string getMessage() { return what(); } }; // class LLCertificate @@ -334,22 +332,22 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred); // All error handling is via exceptions. -class LLCertException +class LLCertException: public std::runtime_error { public: - LLCertException(LLPointer cert, const char* msg) + LLCertException(LLPointer cert, const std::string& msg): + std::runtime_error(msg) { mCert = cert; - LL_WARNS("SECAPI") << "Certificate Error: " << (std::string)msg << LL_ENDL; - mMsg = (std::string)msg; + LL_WARNS("SECAPI") << "Certificate Error: " << msg << LL_ENDL; } + virtual ~LLCertException() throw() {} LLPointer getCert() { return mCert; } - std::string getMessage() { return mMsg; } + std::string getMessage() { return what(); } protected: LLPointer mCert; - std::string mMsg; }; class LLInvalidCertificate : public LLCertException @@ -358,6 +356,7 @@ public: LLInvalidCertificate(LLPointer cert) : LLCertException(cert, "CertInvalid") { } + virtual ~LLInvalidCertificate() throw() {} protected: }; @@ -367,6 +366,7 @@ public: LLCertValidationTrustException(LLPointer cert) : LLCertException(cert, "CertUntrusted") { } + virtual ~LLCertValidationTrustException() throw() {} protected: }; @@ -378,7 +378,7 @@ public: { mHostname = hostname; } - + virtual ~LLCertValidationHostnameException() throw() {} std::string getHostname() { return mHostname; } protected: std::string mHostname; @@ -392,6 +392,7 @@ public: { mTime = current_time; } + virtual ~LLCertValidationExpirationException() throw() {} LLDate GetTime() { return mTime; } protected: LLDate mTime; @@ -403,6 +404,7 @@ public: LLCertKeyUsageValidationException(LLPointer cert) : LLCertException(cert, "CertKeyUsage") { } + virtual ~LLCertKeyUsageValidationException() throw() {} protected: }; @@ -412,6 +414,7 @@ public: LLCertBasicConstraintsValidationException(LLPointer cert) : LLCertException(cert, "CertBasicConstraints") { } + virtual ~LLCertBasicConstraintsValidationException() throw() {} protected: }; @@ -421,6 +424,7 @@ public: LLCertValidationInvalidSignatureException(LLPointer cert) : LLCertException(cert, "CertInvalidSignature") { } + virtual ~LLCertValidationInvalidSignatureException() throw() {} protected: }; diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp index a0e2c0b362..4432c6574e 100644 --- a/indra/viewer_components/updater/llupdateinstaller.cpp +++ b/indra/viewer_components/updater/llupdateinstaller.cpp @@ -35,12 +35,14 @@ #pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!). #endif #include - +#include namespace { - class RelocateError {}; - - + struct RelocateError: public std::runtime_error + { + RelocateError(): std::runtime_error("llupdateinstaller: RelocateError") {} + }; + std::string copy_to_temp(std::string const & path) { std::string scriptFile = gDirUtilp->getBaseFileName(path); -- cgit v1.2.3 From 75149be061fab7c8d7ce0e24e0c9ad0e52d0dd5b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 13 Jul 2016 14:19:26 -0400 Subject: MAINT-5011: Wrap thrown png_const_charp in new PngError class derived from std::runtime_error. --- indra/llimage/llpngwrapper.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index aad139f570..4292f29acc 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -31,6 +31,13 @@ #include "llimage.h" #include "llpngwrapper.h" +#include + +struct PngError: public std::runtime_error +{ + PngError(png_const_charp msg): std::runtime_error(msg) {} +}; + // --------------------------------------------------------------------------- // LLPngWrapper // --------------------------------------------------------------------------- @@ -75,11 +82,10 @@ BOOL LLPngWrapper::isValidPng(U8* src) } // Called by the libpng library when a fatal encoding or decoding error -// occurs. We simply throw the error message and let our try/catch -// block clean up. +// occurs. We throw PngError and let our try/catch block clean up. void LLPngWrapper::errorHandler(png_structp png_ptr, png_const_charp msg) { - throw msg; + throw PngError(msg); } // Called by the libpng library when reading (decoding) the PNG file. We @@ -129,7 +135,7 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf this, &errorHandler, NULL); if (mReadPngPtr == NULL) { - throw "Problem creating png read structure"; + throw PngError("Problem creating png read structure"); } // Allocate/initialize the memory for image information. @@ -187,9 +193,9 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf mFinalSize = dataPtr.mOffset; } - catch (png_const_charp msg) + catch (const PngError& msg) { - mErrorMessage = msg; + mErrorMessage = msg.what(); releaseResources(); return (FALSE); } @@ -288,14 +294,14 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest) if (mColorType == -1) { - throw "Unsupported image: unexpected number of channels"; + throw PngError("Unsupported image: unexpected number of channels"); } mWritePngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &errorHandler, NULL); if (!mWritePngPtr) { - throw "Problem creating png write structure"; + throw PngError("Problem creating png write structure"); } mWriteInfoPtr = png_create_info_struct(mWritePngPtr); @@ -339,9 +345,9 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest) png_write_end(mWritePngPtr, mWriteInfoPtr); mFinalSize = dataPtr.mOffset; } - catch (png_const_charp msg) + catch (const PngError& msg) { - mErrorMessage = msg; + mErrorMessage = msg.what(); releaseResources(); return (FALSE); } -- cgit v1.2.3 From 5b233bba3f885cd7f6202a70677d7ae2970bdfeb Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 13 Jul 2016 14:28:45 -0400 Subject: MAINT-5011: Remove alarming ll_kdu_error() function whose body reads: // *FIX: This exception is bad, bad, bad. It gets thrown from a // destructor which can lead to immediate program termination! throw "ll_kdu_error() throwing an exception"; which would be bad indeed... if ll_kdu_error() were ever actually referenced by anything! --- indra/llkdu/llimagej2ckdu.cpp | 7 ------- 1 file changed, 7 deletions(-) (limited to 'indra') diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 282c859e9e..94c7dbdd23 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -128,13 +128,6 @@ private: S32 mRowGap; }; -void ll_kdu_error( void ) -{ - // *FIX: This exception is bad, bad, bad. It gets thrown from a - // destructor which can lead to immediate program termination! - throw "ll_kdu_error() throwing an exception"; -} - // Stuff for new kdu error handling class LLKDUMessageWarning : public kdu_message { -- cgit v1.2.3 From 21e8352de6c4d662ffdb44d31294ce9caca86517 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 13 Jul 2016 14:42:44 -0400 Subject: MAINT-5011: Introduce KduError instead of throw/catch const char*. KduError is derived from std::runtime_error, so the message string becomes its what() message. --- indra/llkdu/llimagej2ckdu.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'indra') diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 94c7dbdd23..50c2e03cd4 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -34,6 +34,13 @@ #include "kdu_block_coding.h" +#include + +struct KduError: public std::runtime_error +{ + KduError(const std::string& msg): std::runtime_error(msg) {} +}; + class kdc_flow_control { public: @@ -171,7 +178,7 @@ void LLKDUMessageError::flush(bool end_of_message) { if (end_of_message) { - throw "KDU throwing an exception"; + throw KduError("LLKDUMessageError::flush()"); } } @@ -415,9 +422,9 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco mTPosp->x = 0; } } - catch (const char* msg) + catch (const KduError& msg) { - base.setLastError(ll_safe_string(msg)); + base.setLastError(msg.what()); return FALSE; } catch (...) @@ -505,9 +512,9 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco return FALSE; } } - catch (const char* msg) + catch (const KduError& msg) { - base.setLastError(ll_safe_string(msg)); + base.setLastError(msg.what()); base.decodeFailed(); cleanupCodeStream(); return TRUE; // done @@ -698,9 +705,9 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co base.updateData(); // set width, height delete[] output_buffer; } - catch(const char* msg) + catch(const KduError& msg) { - base.setLastError(ll_safe_string(msg)); + base.setLastError(msg.what()); return FALSE; } catch( ... ) @@ -722,9 +729,9 @@ BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base) setupCodeStream(base, FALSE, MODE_FAST); return TRUE; } - catch (const char* msg) + catch (const KduError& msg) { - base.setLastError(ll_safe_string(msg)); + base.setLastError(msg.what()); return FALSE; } catch (...) -- cgit v1.2.3 From 2f003fd5a99f9b9f42b74a70d3a53e818b9bcee4 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 13 Jul 2016 14:58:12 -0400 Subject: MAINT-5011: Throw an actual exception in Force Software Exception. http://en.cppreference.com/w/cpp/language/throw says of the plain throw syntax: "This form is only allowed when an exception is presently being handled (it calls std::terminate if used otherwise)." On advice from Oz, replace plain 'throw;' with throwing a std::runtime_error. --- indra/newview/llappviewer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 604e45f314..a812a5e518 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -231,6 +231,7 @@ #include "llcoproceduremanager.h" #include "llviewereventrecorder.h" +#include // *FIX: These extern globals should be cleaned up. // The globals either represent state/config/resource-storage of either @@ -5512,8 +5513,7 @@ void LLAppViewer::forceErrorInfiniteLoop() void LLAppViewer::forceErrorSoftwareException() { LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL; - // *FIX: Any way to insure it won't be handled? - throw; + throw std::runtime_error("User selected Force Software Exception"); } void LLAppViewer::forceErrorDriverCrash() -- cgit v1.2.3 From d7c904632b9dac112228092952f993569477366c Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Jul 2016 10:26:57 -0400 Subject: MAINT-5011: On advice from NickyD, say KDUError not KduError. Also place KDUError into anonymous namespace to emphasize that it's entirely local to this .cpp file. --- indra/llkdu/llimagej2ckdu.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 50c2e03cd4..2a5b24fbc1 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -36,10 +36,12 @@ #include -struct KduError: public std::runtime_error +namespace { +struct KDUError: public std::runtime_error { - KduError(const std::string& msg): std::runtime_error(msg) {} + KDUError(const std::string& msg): std::runtime_error(msg) {} }; +} // anonymous namespace class kdc_flow_control { @@ -178,7 +180,7 @@ void LLKDUMessageError::flush(bool end_of_message) { if (end_of_message) { - throw KduError("LLKDUMessageError::flush()"); + throw KDUError("LLKDUMessageError::flush()"); } } @@ -422,7 +424,7 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco mTPosp->x = 0; } } - catch (const KduError& msg) + catch (const KDUError& msg) { base.setLastError(msg.what()); return FALSE; @@ -512,7 +514,7 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco return FALSE; } } - catch (const KduError& msg) + catch (const KDUError& msg) { base.setLastError(msg.what()); base.decodeFailed(); @@ -705,7 +707,7 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co base.updateData(); // set width, height delete[] output_buffer; } - catch(const KduError& msg) + catch(const KDUError& msg) { base.setLastError(msg.what()); return FALSE; @@ -729,7 +731,7 @@ BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base) setupCodeStream(base, FALSE, MODE_FAST); return TRUE; } - catch (const KduError& msg) + catch (const KDUError& msg) { base.setLastError(msg.what()); return FALSE; -- cgit v1.2.3 From 636ce117bb1b3bda30ff725d41b50ed2c48e4bf0 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Jul 2016 10:35:56 -0400 Subject: MAINT-5011: Per NickyD, put PngError in anonymous namespace. --- indra/llimage/llpngwrapper.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index 4292f29acc..531859cbc9 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -33,10 +33,12 @@ #include +namespace { struct PngError: public std::runtime_error { PngError(png_const_charp msg): std::runtime_error(msg) {} }; +} // anonymous namespace // --------------------------------------------------------------------------- // LLPngWrapper -- cgit v1.2.3 From cefa598e49490bfedb86a5be0747ec3c856d06bf Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 14 Jul 2016 11:33:29 -0400 Subject: MAINT-5011: Per NickyD, make LLCertException::getMessage() const. Also getCert(). Also LLProtectedDataException::getMessage(). --- indra/newview/llsecapi.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 02438f77b7..55c6d95cd8 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -124,7 +124,7 @@ struct LLProtectedDataException: public std::runtime_error { LL_WARNS("SECAPI") << "Protected Data Error: " << msg << LL_ENDL; } - std::string getMessage() { return what(); } + std::string getMessage() const { return what(); } }; // class LLCertificate @@ -344,8 +344,8 @@ public: LL_WARNS("SECAPI") << "Certificate Error: " << msg << LL_ENDL; } virtual ~LLCertException() throw() {} - LLPointer getCert() { return mCert; } - std::string getMessage() { return what(); } + LLPointer getCert() const { return mCert; } + std::string getMessage() const { return what(); } protected: LLPointer mCert; }; -- cgit v1.2.3 From 47d93e4f65493977217cfed53ff68eb926cf9bb7 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 19 Jul 2016 14:08:43 -0400 Subject: DRTVWR-418: Remove rogue getMessage() from llsecapi.h exceptions. The LLProtectedDataException and LLCertException exception classes didn't used to be derived from std::exception, so they followed their own getMessage() convention instead of the standard what() convention. Now that they're derived from std::exception, remove getMessage() and change its few consumers to use what() instead. Thanks NickyD for suggesting. --- indra/newview/llappcorehttp.cpp | 4 ++-- indra/newview/llsecapi.cpp | 2 +- indra/newview/llsecapi.h | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index 49291ea564..dbcae57de7 100644 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -534,7 +534,7 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url, // somewhat clumsy, as we may run into errors that do not map directly to curl // error codes. Should be refactored with login refactoring, perhaps. result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CACERT); - result.setMessage(cert_exception.getMessage()); + result.setMessage(cert_exception.what()); LLPointer cert = cert_exception.getCert(); cert->ref(); // adding an extra ref here result.setErrorData(cert.get()); @@ -544,7 +544,7 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url, catch (LLCertException &cert_exception) { result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_PEER_CERTIFICATE); - result.setMessage(cert_exception.getMessage()); + result.setMessage(cert_exception.what()); LLPointer cert = cert_exception.getCert(); cert->ref(); // adding an extra ref here result.setErrorData(cert.get()); diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index c27709a57b..e871570786 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -64,7 +64,7 @@ void initializeSecHandler() } catch (LLProtectedDataException e) { - exception_msg = e.getMessage(); + exception_msg = e.what(); } } if (!exception_msg.empty()) // an exception was thrown. diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 55c6d95cd8..535a112638 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -124,7 +124,6 @@ struct LLProtectedDataException: public std::runtime_error { LL_WARNS("SECAPI") << "Protected Data Error: " << msg << LL_ENDL; } - std::string getMessage() const { return what(); } }; // class LLCertificate @@ -345,7 +344,6 @@ public: } virtual ~LLCertException() throw() {} LLPointer getCert() const { return mCert; } - std::string getMessage() const { return what(); } protected: LLPointer mCert; }; -- cgit v1.2.3 From 9c49a6c91dd9b5bbe811fcd91d8992ed6bac33e7 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 19 Jul 2016 16:25:25 -0400 Subject: MAINT-5011: Introduce LLException base class for viewer exceptions. This also introduces LLContinueError for exceptions which should interrupt some part of viewer processing (e.g. the current coroutine) but should attempt to let the viewer session proceed. Derive all existing viewer exception classes from LLException rather than from std::runtime_error or std::logic_error. Use BOOST_THROW_EXCEPTION() rather than plain 'throw' to enrich the thrown exception with source file, line number and containing function. --- indra/llcommon/CMakeLists.txt | 1 + indra/llcommon/lldependencies.cpp | 3 +- indra/llcommon/lldependencies.h | 6 +-- indra/llcommon/lleventcoro.cpp | 3 +- indra/llcommon/lleventcoro.h | 6 +-- indra/llcommon/llevents.cpp | 17 +++--- indra/llcommon/llevents.h | 14 ++--- indra/llcommon/llexception.h | 63 ++++++++++++++++++++++ indra/llcommon/llleap.cpp | 5 +- indra/llcommon/llleap.h | 6 +-- indra/llcommon/llprocess.cpp | 23 ++++---- indra/llcommon/llprocess.h | 6 +-- indra/llcommon/llthreadsafequeue.cpp | 13 ++--- indra/llcommon/llthreadsafequeue.h | 7 ++- indra/llcommon/lluuid.cpp | 2 +- indra/llcommon/tests/wrapllerrs.h | 9 ++-- indra/llimage/llpngwrapper.cpp | 15 +++--- indra/llkdu/llimagej2ckdu.cpp | 9 ++-- indra/llmessage/llhttpnode.cpp | 15 +++--- indra/llmessage/tests/commtest.h | 9 ++-- indra/llmessage/tests/networkio.h | 6 ++- indra/newview/llappviewer.cpp | 6 +-- indra/newview/llcommandlineparser.cpp | 25 +++++---- indra/newview/llsecapi.cpp | 3 +- indra/newview/llsecapi.h | 10 ++-- indra/newview/llsechandler_basic.cpp | 53 +++++++++--------- .../updater/llupdatedownloader.cpp | 17 +++--- .../updater/llupdateinstaller.cpp | 9 ++-- .../viewer_components/updater/llupdaterservice.cpp | 11 ++-- indra/viewer_components/updater/llupdaterservice.h | 5 +- 30 files changed, 234 insertions(+), 143 deletions(-) create mode 100644 indra/llcommon/llexception.h (limited to 'indra') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 907dbab8f8..44f45144e5 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -157,6 +157,7 @@ set(llcommon_HEADER_FILES lleventfilter.h llevents.h lleventemitter.h + llexception.h llfasttimer.h llfile.h llfindlocale.h diff --git a/indra/llcommon/lldependencies.cpp b/indra/llcommon/lldependencies.cpp index 0e72c175cb..87a699ff14 100644 --- a/indra/llcommon/lldependencies.cpp +++ b/indra/llcommon/lldependencies.cpp @@ -39,6 +39,7 @@ #include #include #include +#include // other Linden headers LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const @@ -76,7 +77,7 @@ LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const // Omit independent nodes: display only those that might contribute to // the cycle. describe(out, false); - throw Cycle(out.str()); + BOOST_THROW_EXCEPTION(Cycle(out.str())); } // A peculiarity of boost::topological_sort() is that it emits results in // REVERSE topological order: to get the result you want, you must diff --git a/indra/llcommon/lldependencies.h b/indra/llcommon/lldependencies.h index e0294e271b..125bd6a835 100644 --- a/indra/llcommon/lldependencies.h +++ b/indra/llcommon/lldependencies.h @@ -34,13 +34,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include "llexception.h" /***************************************************************************** * Utilities @@ -106,9 +106,9 @@ public: /** * Exception thrown by sort() if there's a cycle */ - struct Cycle: public std::runtime_error + struct Cycle: public LLException { - Cycle(const std::string& what): std::runtime_error(what) {} + Cycle(const std::string& what): LLException(what) {} }; /** diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index 2d5f964deb..f444530a17 100644 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp @@ -34,6 +34,7 @@ #include // std headers // external library headers +#include // other Linden headers #include "llsdserialize.h" #include "llerror.h" @@ -351,7 +352,7 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc) // returning it, deliver it via exception. if (result.second) { - throw LLErrorEvent(desc, result.first); + BOOST_THROW_EXCEPTION(LLErrorEvent(desc, result.first)); } // That way, our caller knows a simple return must be from the reply // pump (pump 0). diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h index 87926c692d..84827aab4a 100644 --- a/indra/llcommon/lleventcoro.h +++ b/indra/llcommon/lleventcoro.h @@ -31,10 +31,10 @@ #include #include -#include #include // std::pair #include "llevents.h" #include "llerror.h" +#include "llexception.h" /** * Like LLListenerOrPumpName, this is a class intended for parameter lists: @@ -234,11 +234,11 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc); * because it's not an error in event processing: rather, this exception * announces an event that bears error information (for some other API). */ -class LL_COMMON_API LLErrorEvent: public std::runtime_error +class LL_COMMON_API LLErrorEvent: public LLException { public: LLErrorEvent(const std::string& what, const LLSD& data): - std::runtime_error(what), + LLException(what), mData(data) {} virtual ~LLErrorEvent() throw() {} diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 645c29d770..50919edb8e 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -45,6 +45,7 @@ #include // external library headers #include +#include #if LL_WINDOWS #pragma warning (push) #pragma warning (disable : 4701) // compiler thinks might use uninitialized var, but no @@ -174,7 +175,7 @@ std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string // Unless we're permitted to tweak it, that's Bad. if (! tweak) { - throw LLEventPump::DupPumpName(std::string("Duplicate LLEventPump name '") + name + "'"); + BOOST_THROW_EXCEPTION(LLEventPump::DupPumpName(std::string("Duplicate LLEventPump name '") + name + "'")); } // The passed name isn't unique, but we're permitted to tweak it. Find the // first decimal-integer suffix not already taken. The insert() attempt @@ -326,8 +327,9 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL // is only when the existing connection object is still connected. if (found != mConnections.end() && found->second.connected()) { - throw DupListenerName(std::string("Attempt to register duplicate listener name '") + name + - "' on " + typeid(*this).name() + " '" + getName() + "'"); + BOOST_THROW_EXCEPTION( + DupListenerName(std::string("Attempt to register duplicate listener name '") + name + + "' on " + typeid(*this).name() + " '" + getName() + "'")); } // Okay, name is unique, try to reconcile its dependencies. Specify a new // "node" value that we never use for an mSignal placement; we'll fix it @@ -353,8 +355,9 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL // unsortable. If we leave the new node in mDeps, it will continue // to screw up all future attempts to sort()! Pull it out. mDeps.remove(name); - throw Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() + - " '" + getName() + "' would cause cycle: " + e.what()); + BOOST_THROW_EXCEPTION( + Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() + + " '" + getName() + "' would cause cycle: " + e.what())); } // Walk the list to verify that we haven't changed the order. float previous = 0.0, myprev = 0.0; @@ -418,7 +421,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL // NOW remove the offending listener node. mDeps.remove(name); // Having constructed a description of the order change, inform caller. - throw OrderChange(out.str()); + BOOST_THROW_EXCEPTION(OrderChange(out.str())); } // This node becomes the previous one. previous = dmi->second; @@ -608,7 +611,7 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const { if (! mListener) { - throw Empty("attempting to call uninitialized"); + BOOST_THROW_EXCEPTION(Empty("attempting to call uninitialized")); } return (*mListener)(event); } diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index ba4fcd766e..8ff337911d 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -37,7 +37,6 @@ #include #include #include -#include #if LL_WINDOWS #pragma warning (push) #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch @@ -62,6 +61,7 @@ #include "llsingleton.h" #include "lldependencies.h" #include "llstl.h" +#include "llexception.h" /*==========================================================================*| // override this to allow binding free functions with more parameters @@ -188,10 +188,10 @@ public: bool operator()(const LLSD& event) const; /// exception if you try to call when empty - struct Empty: public std::runtime_error + struct Empty: public LLException { Empty(const std::string& what): - std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {} + LLException(std::string("LLListenerOrPumpName::Empty: ") + what) {} }; private: @@ -371,10 +371,10 @@ public: * you didn't pass tweak=true to permit it to generate a unique * variant. */ - struct DupPumpName: public std::runtime_error + struct DupPumpName: public LLException { DupPumpName(const std::string& what): - std::runtime_error(std::string("DupPumpName: ") + what) {} + LLException(std::string("DupPumpName: ") + what) {} }; /** @@ -399,9 +399,9 @@ public: /// group exceptions thrown by listen(). We use exceptions because these /// particular errors are likely to be coding errors, found and fixed by /// the developer even before preliminary checkin. - struct ListenError: public std::runtime_error + struct ListenError: public LLException { - ListenError(const std::string& what): std::runtime_error(what) {} + ListenError(const std::string& what): LLException(what) {} }; /** * exception thrown by listen(). You are attempting to register a diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h new file mode 100644 index 0000000000..3ac2f4762f --- /dev/null +++ b/indra/llcommon/llexception.h @@ -0,0 +1,63 @@ +/** + * @file llexception.h + * @author Nat Goodspeed + * @date 2016-06-29 + * @brief Types needed for generic exception handling + * + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLEXCEPTION_H) +#define LL_LLEXCEPTION_H + +#include +#include + +/** + * LLException is intended as the common base class from which all + * viewer-specific exceptions are derived. It is itself a subclass of + * boost::exception; use catch (const boost::exception& e) clause to log the + * string from boost::diagnostic_information(e). + * + * Since it is also derived from std::exception, a generic catch (const + * std::exception&) should also work, though what() is unlikely to be as + * informative as boost::diagnostic_information(). + * + * Please use BOOST_THROW_EXCEPTION() + * http://www.boost.org/doc/libs/release/libs/exception/doc/BOOST_THROW_EXCEPTION.html + * to throw viewer exceptions whenever possible. This enriches the exception's + * diagnostic_information() with the source file, line and containing function + * of the BOOST_THROW_EXCEPTION() macro. + * + * There may be circumstances in which it would be valuable to distinguish an + * exception explicitly thrown by viewer code from an exception thrown by + * (say) a third-party library. Catching (const LLException&) supports such + * usage. However, most of the value of this base class is in the + * diagnostic_information() available via Boost.Exception. + */ +struct LLException: + public std::runtime_error, + public boost::exception +{ + LLException(const std::string& what): + std::runtime_error(what) + {} +}; + +/** + * The point of LLContinueError is to distinguish exceptions that need not + * terminate the whole viewer session. In general, an uncaught exception will + * be logged and will crash the viewer. However, though an uncaught exception + * derived from LLContinueError will still be logged, the viewer will attempt + * to continue processing. + */ +struct LLContinueError: public LLException +{ + LLContinueError(const std::string& what): + LLException(what) + {} +}; + +#endif /* ! defined(LL_LLEXCEPTION_H) */ diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index 84d2a12f65..a8bb9bc53a 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -21,6 +21,7 @@ #include #include #include +#include // other Linden headers #include "llerror.h" #include "llstring.h" @@ -69,7 +70,7 @@ public: // Rule out empty vector if (plugin.empty()) { - throw Error("no plugin command"); + BOOST_THROW_EXCEPTION(Error("no plugin command")); } // Don't leave desc empty either, but in this case, if we weren't @@ -112,7 +113,7 @@ public: // If that didn't work, no point in keeping this LLLeap object. if (! mChild) { - throw Error(STRINGIZE("failed to run " << mDesc)); + BOOST_THROW_EXCEPTION(Error(STRINGIZE("failed to run " << mDesc))); } // Okay, launch apparently worked. Change our mDonePump listener. diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h index e33f25e530..8aac8a64c5 100644 --- a/indra/llcommon/llleap.h +++ b/indra/llcommon/llleap.h @@ -13,9 +13,9 @@ #define LL_LLLEAP_H #include "llinstancetracker.h" +#include "llexception.h" #include #include -#include /** * LLSD Event API Plugin class. Because instances are managed by @@ -67,9 +67,9 @@ public: * string(s) passed to create() might come from an external source. This * way the caller can catch LLLeap::Error and try to recover. */ - struct Error: public std::runtime_error + struct Error: public LLException { - Error(const std::string& what): std::runtime_error(what) {} + Error(const std::string& what): LLException(what) {} }; virtual ~LLLeap(); diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 44f56daf2d..ca19c94736 100644 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -472,9 +473,9 @@ private: *****************************************************************************/ /// Need an exception to avoid constructing an invalid LLProcess object, but /// internal use only -struct LLProcessError: public std::runtime_error +struct LLProcessError: public LLException { - LLProcessError(const std::string& msg): std::runtime_error(msg) {} + LLProcessError(const std::string& msg): LLException(msg) {} }; LLProcessPtr LLProcess::create(const LLSDOrParams& params) @@ -530,8 +531,9 @@ LLProcess::LLProcess(const LLSDOrParams& params): if (! params.validateBlock(true)) { - throw LLProcessError(STRINGIZE("not launched: failed parameter validation\n" - << LLSDNotationStreamer(params))); + BOOST_THROW_EXCEPTION( + LLProcessError(STRINGIZE("not launched: failed parameter validation\n" + << LLSDNotationStreamer(params)))); } mPostend = params.postend; @@ -596,10 +598,11 @@ LLProcess::LLProcess(const LLSDOrParams& params): } else { - throw LLProcessError(STRINGIZE("For " << params.executable() - << ": unsupported FileParam for " << which - << ": type='" << fparam.type() - << "', name='" << fparam.name() << "'")); + BOOST_THROW_EXCEPTION( + LLProcessError(STRINGIZE("For " << params.executable() + << ": unsupported FileParam for " << which + << ": type='" << fparam.type() + << "', name='" << fparam.name() << "'"))); } } // By default, pass APR_NO_PIPE for unspecified slots. @@ -678,7 +681,7 @@ LLProcess::LLProcess(const LLSDOrParams& params): if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr, gAPRPoolp))) { - throw LLProcessError(STRINGIZE(params << " failed")); + BOOST_THROW_EXCEPTION(LLProcessError(STRINGIZE(params << " failed"))); } // arrange to call status_callback() @@ -1063,7 +1066,7 @@ PIPETYPE& LLProcess::getPipe(FILESLOT slot) PIPETYPE* wp = getPipePtr(error, slot); if (! wp) { - throw NoPipe(error); + BOOST_THROW_EXCEPTION(NoPipe(error)); } return *wp; } diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h index 43ccadc412..bfac4567a5 100644 --- a/indra/llcommon/llprocess.h +++ b/indra/llcommon/llprocess.h @@ -30,13 +30,13 @@ #include "llinitparam.h" #include "llsdparam.h" #include "llwin32headerslean.h" +#include "llexception.h" #include "apr_thread_proc.h" #include #include #include #include #include // std::ostream -#include #if LL_WINDOWS #include "llwin32headerslean.h" // for HANDLE @@ -479,9 +479,9 @@ public: /// Exception thrown by getWritePipe(), getReadPipe() if you didn't ask to /// create a pipe at the corresponding FILESLOT. - struct NoPipe: public std::runtime_error + struct NoPipe: public LLException { - NoPipe(const std::string& what): std::runtime_error(what) {} + NoPipe(const std::string& what): LLException(what) {} }; /** diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp index 185f0d63fb..a004618e96 100644 --- a/indra/llcommon/llthreadsafequeue.cpp +++ b/indra/llcommon/llthreadsafequeue.cpp @@ -26,6 +26,7 @@ #include "linden_common.h" #include #include +#include #include "llthreadsafequeue.h" @@ -41,13 +42,13 @@ LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * po { if(mOwnsPool) { apr_status_t status = apr_pool_create(&mPool, 0); - if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate pool"); + if(status != APR_SUCCESS) BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("failed to allocate pool")); } else { ; // No op. } apr_status_t status = apr_queue_create(&mQueue, capacity, mPool); - if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate queue"); + if(status != APR_SUCCESS) BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("failed to allocate queue")); } @@ -68,9 +69,9 @@ void LLThreadSafeQueueImplementation::pushFront(void * element) apr_status_t status = apr_queue_push(mQueue, element); if(status == APR_EINTR) { - throw LLThreadSafeQueueInterrupt(); + BOOST_THROW_EXCEPTION(LLThreadSafeQueueInterrupt()); } else if(status != APR_SUCCESS) { - throw LLThreadSafeQueueError("push failed"); + BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("push failed")); } else { ; // Success. } @@ -88,9 +89,9 @@ void * LLThreadSafeQueueImplementation::popBack(void) apr_status_t status = apr_queue_pop(mQueue, &element); if(status == APR_EINTR) { - throw LLThreadSafeQueueInterrupt(); + BOOST_THROW_EXCEPTION(LLThreadSafeQueueInterrupt()); } else if(status != APR_SUCCESS) { - throw LLThreadSafeQueueError("pop failed"); + BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("pop failed")); } else { return element; } diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h index 58cac38769..45289ef0b4 100644 --- a/indra/llcommon/llthreadsafequeue.h +++ b/indra/llcommon/llthreadsafequeue.h @@ -27,9 +27,8 @@ #ifndef LL_LLTHREADSAFEQUEUE_H #define LL_LLTHREADSAFEQUEUE_H - +#include "llexception.h" #include -#include struct apr_pool_t; // From apr_pools.h @@ -40,11 +39,11 @@ class LLThreadSafeQueueImplementation; // See below. // A general queue exception. // class LL_COMMON_API LLThreadSafeQueueError: -public std::runtime_error + public LLException { public: LLThreadSafeQueueError(std::string const & message): - std::runtime_error(message) + LLException(message) { ; // No op. } diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index e3671047b4..785cf47926 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -83,7 +83,7 @@ unsigned int decode( char const * fiveChars ) throw( bad_input_data ) unsigned int ret = 0; for( int ix = 0; ix < 5; ++ix ) { char * s = strchr( encodeTable, fiveChars[ ix ] ); -if( s == 0 ) throw bad_input_data(); +if( s == 0 ) BOOST_THROW_EXCEPTION(bad_input_data()); ret = ret * 85 + (s-encodeTable); } return ret; diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index 785197ba11..fa16fd6915 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -35,13 +35,14 @@ #include #include "llerrorcontrol.h" +#include "llexception.h" #include "stringize.h" #include #include #include +#include #include #include -#include // statically reference the function in test.cpp... it's short, we could // replicate, but better to reuse @@ -67,9 +68,9 @@ struct WrapLLErrs LLError::restoreSettings(mPriorErrorSettings); } - struct FatalException: public std::runtime_error + struct FatalException: public LLException { - FatalException(const std::string& what): std::runtime_error(what) {} + FatalException(const std::string& what): LLException(what) {} }; void operator()(const std::string& message) @@ -78,7 +79,7 @@ struct WrapLLErrs error = message; // Also throw an appropriate exception since calling code is likely to // assume that control won't continue beyond LL_ERRS. - throw FatalException(message); + BOOST_THROW_EXCEPTION(FatalException(message)); } std::string error; diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index 531859cbc9..0b7d4c717f 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -31,12 +31,13 @@ #include "llimage.h" #include "llpngwrapper.h" -#include +#include "llexception.h" +#include namespace { -struct PngError: public std::runtime_error +struct PngError: public LLException { - PngError(png_const_charp msg): std::runtime_error(msg) {} + PngError(png_const_charp msg): LLException(msg) {} }; } // anonymous namespace @@ -87,7 +88,7 @@ BOOL LLPngWrapper::isValidPng(U8* src) // occurs. We throw PngError and let our try/catch block clean up. void LLPngWrapper::errorHandler(png_structp png_ptr, png_const_charp msg) { - throw PngError(msg); + BOOST_THROW_EXCEPTION(PngError(msg)); } // Called by the libpng library when reading (decoding) the PNG file. We @@ -137,7 +138,7 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf this, &errorHandler, NULL); if (mReadPngPtr == NULL) { - throw PngError("Problem creating png read structure"); + BOOST_THROW_EXCEPTION(PngError("Problem creating png read structure")); } // Allocate/initialize the memory for image information. @@ -296,14 +297,14 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest) if (mColorType == -1) { - throw PngError("Unsupported image: unexpected number of channels"); + BOOST_THROW_EXCEPTION(PngError("Unsupported image: unexpected number of channels")); } mWritePngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &errorHandler, NULL); if (!mWritePngPtr) { - throw PngError("Problem creating png write structure"); + BOOST_THROW_EXCEPTION(PngError("Problem creating png write structure")); } mWriteInfoPtr = png_create_info_struct(mWritePngPtr); diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 2a5b24fbc1..fa58931407 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -34,12 +34,13 @@ #include "kdu_block_coding.h" -#include +#include "llexception.h" +#include namespace { -struct KDUError: public std::runtime_error +struct KDUError: public LLException { - KDUError(const std::string& msg): std::runtime_error(msg) {} + KDUError(const std::string& msg): LLException(msg) {} }; } // anonymous namespace @@ -180,7 +181,7 @@ void LLKDUMessageError::flush(bool end_of_message) { if (end_of_message) { - throw KDUError("LLKDUMessageError::flush()"); + BOOST_THROW_EXCEPTION(KDUError("LLKDUMessageError::flush()")); } } diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp index 08688ca48b..48ce258ba2 100644 --- a/indra/llmessage/llhttpnode.cpp +++ b/indra/llmessage/llhttpnode.cpp @@ -31,7 +31,8 @@ #include "llstl.h" #include "llhttpconstants.h" -#include +#include "llexception.h" +#include const std::string CONTEXT_HEADERS("headers"); const std::string CONTEXT_PATH("path"); @@ -93,28 +94,28 @@ LLHTTPNode::~LLHTTPNode() namespace { - struct NotImplemented: public std::runtime_error + struct NotImplemented: public LLException { - NotImplemented(): std::runtime_error("LLHTTPNode::NotImplemented") {} + NotImplemented(): LLException("LLHTTPNode::NotImplemented") {} }; } // virtual LLSD LLHTTPNode::simpleGet() const { - throw NotImplemented(); + BOOST_THROW_EXCEPTION(NotImplemented()); } // virtual LLSD LLHTTPNode::simplePut(const LLSD& input) const { - throw NotImplemented(); + BOOST_THROW_EXCEPTION(NotImplemented()); } // virtual LLSD LLHTTPNode::simplePost(const LLSD& input) const { - throw NotImplemented(); + BOOST_THROW_EXCEPTION(NotImplemented()); } @@ -174,7 +175,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons // virtual LLSD LLHTTPNode::simpleDel(const LLSD&) const { - throw NotImplemented(); + BOOST_THROW_EXCEPTION(NotImplemented()); } // virtual diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h index 0d149b5258..5dff56b44f 100644 --- a/indra/llmessage/tests/commtest.h +++ b/indra/llmessage/tests/commtest.h @@ -33,15 +33,16 @@ #include "llevents.h" #include "llsd.h" #include "llhost.h" +#include "llexception.h" #include "stringize.h" #include #include -#include #include +#include -struct CommtestError: public std::runtime_error +struct CommtestError: public LLException { - CommtestError(const std::string& what): std::runtime_error(what) {} + CommtestError(const std::string& what): LLException(what) {} }; static bool query_verbose() @@ -68,7 +69,7 @@ static int query_port(const std::string& var) const char* cport = getenv(var.c_str()); if (! cport) { - throw CommtestError(STRINGIZE("missing environment variable" << var)); + BOOST_THROW_EXCEPTION(CommtestError(STRINGIZE("missing environment variable" << var))); } // This will throw, too, if the value of PORT isn't numeric. int port(boost::lexical_cast(cport)); diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h index 2aff90ca1e..6aaecf9bac 100644 --- a/indra/llmessage/tests/networkio.h +++ b/indra/llmessage/tests/networkio.h @@ -34,6 +34,8 @@ #include "llares.h" #include "llpumpio.h" #include "llhttpclient.h" +#include "llexception.h" +#include /***************************************************************************** * NetworkIO @@ -51,7 +53,7 @@ public: ll_init_apr(); if (! gAPRPoolp) { - throw std::runtime_error("Can't initialize APR"); + BOOST_THROW_EXCEPTION(LLException("Can't initialize APR")); } // Create IO Pump to use for HTTP Requests. @@ -59,7 +61,7 @@ public: LLHTTPClient::setPump(*mServicePump); if (ll_init_ares() == NULL || !gAres->isInitialized()) { - throw std::runtime_error("Can't start DNS resolver"); + BOOST_THROW_EXCEPTION(LLException("Can't start DNS resolver")); } // You can interrupt pump() without waiting the full timeout duration diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a812a5e518..fdef556589 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -122,6 +122,7 @@ #include "llleap.h" #include "stringize.h" #include "llcoros.h" +#include "llexception.h" #if !LL_LINUX #include "cef/llceflib.h" #endif @@ -131,6 +132,7 @@ #include #include #include +#include #if LL_WINDOWS # include // For _SH_DENYWR in processMarkerFiles @@ -231,8 +233,6 @@ #include "llcoproceduremanager.h" #include "llviewereventrecorder.h" -#include - // *FIX: These extern globals should be cleaned up. // The globals either represent state/config/resource-storage of either // this app, or another 'component' of the viewer. App globals should be @@ -5513,7 +5513,7 @@ void LLAppViewer::forceErrorInfiniteLoop() void LLAppViewer::forceErrorSoftwareException() { LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL; - throw std::runtime_error("User selected Force Software Exception"); + BOOST_THROW_EXCEPTION(LLException("User selected Force Software Exception")); } void LLAppViewer::forceErrorDriverCrash() diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp index 1819fc74ee..54f96b8872 100644 --- a/indra/newview/llcommandlineparser.cpp +++ b/indra/newview/llcommandlineparser.cpp @@ -26,6 +26,7 @@ #include "llviewerprecompiledheaders.h" #include "llcommandlineparser.h" +#include "llexception.h" // *NOTE: The boost::lexical_cast generates // the warning C4701(local used with out assignment) in VC7.1. @@ -42,6 +43,7 @@ #include #include #include +#include #if _MSC_VER # pragma warning(pop) @@ -98,14 +100,14 @@ namespace bool gPastLastOption = false; } -class LLCLPError : public std::logic_error { +class LLCLPError : public LLException { public: - LLCLPError(const std::string& what) : std::logic_error(what) {} + LLCLPError(const std::string& what) : LLException(what) {} }; -class LLCLPLastOption : public std::logic_error { +class LLCLPLastOption : public LLException { public: - LLCLPLastOption(const std::string& what) : std::logic_error(what) {} + LLCLPLastOption(const std::string& what) : LLException(what) {} }; class LLCLPValue : public po::value_semantic_codecvt_helper @@ -202,17 +204,17 @@ protected: { if(gPastLastOption) { - throw(LLCLPLastOption("Don't parse no more!")); + BOOST_THROW_EXCEPTION(LLCLPLastOption("Don't parse no more!")); } // Error checks. Needed? if (!value_store.empty() && !is_composing()) { - throw(LLCLPError("Non composing value with multiple occurences.")); + BOOST_THROW_EXCEPTION(LLCLPError("Non composing value with multiple occurences.")); } if (new_tokens.size() < min_tokens() || new_tokens.size() > max_tokens()) { - throw(LLCLPError("Illegal number of tokens specified.")); + BOOST_THROW_EXCEPTION(LLCLPError("Illegal number of tokens specified.")); } if(value_store.empty()) @@ -466,7 +468,7 @@ onevalue(const std::string& option, { // What does it mean when the user specifies a command-line switch // that requires a value, but omits the value? Complain. - throw LLCLPError(STRINGIZE("No value specified for --" << option << "!")); + BOOST_THROW_EXCEPTION(LLCLPError(STRINGIZE("No value specified for --" << option << "!"))); } else if (value.size() > 1) { @@ -484,9 +486,10 @@ void badvalue(const std::string& option, // If the user passes an unusable value for a command-line switch, it // seems like a really bad idea to just ignore it, even with a log // warning. - throw LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option - << "' for variable '" << varname << "' of type " << type - << ": '" << value << "'")); + BOOST_THROW_EXCEPTION( + LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option + << "' for variable '" << varname << "' of type " << type + << ": '" << value << "'"))); } template diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index e871570786..bcb9417820 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -29,6 +29,7 @@ #include "llviewerprecompiledheaders.h" #include "llsecapi.h" #include "llsechandler_basic.h" +#include #include #include #include @@ -69,7 +70,7 @@ void initializeSecHandler() } if (!exception_msg.empty()) // an exception was thrown. { - throw LLProtectedDataException(exception_msg); + BOOST_THROW_EXCEPTION(LLProtectedDataException(exception_msg)); } } diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 535a112638..6af5a28fa5 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -32,7 +32,7 @@ #include #include #include "llpointer.h" -#include +#include "llexception.h" #ifdef LL_WINDOWS #pragma warning(disable:4250) @@ -117,10 +117,10 @@ -struct LLProtectedDataException: public std::runtime_error +struct LLProtectedDataException: public LLException { LLProtectedDataException(const std::string& msg): - std::runtime_error(msg) + LLException(msg) { LL_WARNS("SECAPI") << "Protected Data Error: " << msg << LL_ENDL; } @@ -331,11 +331,11 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred); // All error handling is via exceptions. -class LLCertException: public std::runtime_error +class LLCertException: public LLException { public: LLCertException(LLPointer cert, const std::string& msg): - std::runtime_error(msg) + LLException(msg) { mCert = cert; diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 40516f9bbb..39ce64ad0e 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -35,6 +35,7 @@ #include "llfile.h" #include "lldir.h" #include "llviewercontrol.h" +#include #include #include #include @@ -72,14 +73,14 @@ LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert) if(pem_bio == NULL) { LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL; - throw LLInvalidCertificate(this); + BOOST_THROW_EXCEPTION(LLInvalidCertificate(this)); } mCert = NULL; PEM_read_bio_X509(pem_bio, &mCert, 0, NULL); BIO_free(pem_bio); if (!mCert) { - throw LLInvalidCertificate(this); + BOOST_THROW_EXCEPTION(LLInvalidCertificate(this)); } } @@ -88,7 +89,7 @@ LLBasicCertificate::LLBasicCertificate(X509* pCert) { if (!pCert || !pCert->cert_info) { - throw LLInvalidCertificate(this); + BOOST_THROW_EXCEPTION(LLInvalidCertificate(this)); } mCert = X509_dup(pCert); } @@ -873,22 +874,22 @@ void _validateCert(int validation_policy, // check basic properties exist in the cert if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info.has(CERT_SUBJECT_NAME_STRING)) { - throw LLCertException(cert, "Cert doesn't have a Subject Name"); + BOOST_THROW_EXCEPTION(LLCertException(cert, "Cert doesn't have a Subject Name")); } if(!current_cert_info.has(CERT_ISSUER_NAME_STRING)) { - throw LLCertException(cert, "Cert doesn't have an Issuer Name"); + BOOST_THROW_EXCEPTION(LLCertException(cert, "Cert doesn't have an Issuer Name")); } // check basic properties exist in the cert if(!current_cert_info.has(CERT_VALID_FROM) || !current_cert_info.has(CERT_VALID_TO)) { - throw LLCertException(cert, "Cert doesn't have an expiration period"); + BOOST_THROW_EXCEPTION(LLCertException(cert, "Cert doesn't have an expiration period")); } if (!current_cert_info.has(CERT_SHA1_DIGEST)) { - throw LLCertException(cert, "No SHA1 digest"); + BOOST_THROW_EXCEPTION(LLCertException(cert, "No SHA1 digest")); } if (validation_policy & VALIDATION_POLICY_TIME) @@ -903,7 +904,7 @@ void _validateCert(int validation_policy, if((validation_date < current_cert_info[CERT_VALID_FROM].asDate()) || (validation_date > current_cert_info[CERT_VALID_TO].asDate())) { - throw LLCertValidationExpirationException(cert, validation_date); + BOOST_THROW_EXCEPTION(LLCertValidationExpirationException(cert, validation_date)); } } if (validation_policy & VALIDATION_POLICY_SSL_KU) @@ -914,14 +915,14 @@ void _validateCert(int validation_policy, !(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE], LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT))))) { - throw LLCertKeyUsageValidationException(cert); + BOOST_THROW_EXCEPTION(LLCertKeyUsageValidationException(cert)); } // only validate EKU if the cert has it if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE) && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray() && (!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE], LLSD((std::string)CERT_EKU_SERVER_AUTH)))) { - throw LLCertKeyUsageValidationException(cert); + BOOST_THROW_EXCEPTION(LLCertKeyUsageValidationException(cert)); } } if (validation_policy & VALIDATION_POLICY_CA_KU) @@ -930,7 +931,7 @@ void _validateCert(int validation_policy, (!_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE], (std::string)CERT_KU_CERT_SIGN))) { - throw LLCertKeyUsageValidationException(cert); + BOOST_THROW_EXCEPTION(LLCertKeyUsageValidationException(cert)); } } @@ -942,13 +943,13 @@ void _validateCert(int validation_policy, if(!current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_CA) || !current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_CA]) { - throw LLCertBasicConstraintsValidationException(cert); + BOOST_THROW_EXCEPTION(LLCertBasicConstraintsValidationException(cert)); } if (current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_PATHLEN) && ((current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger() != 0) && (depth > current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger()))) { - throw LLCertBasicConstraintsValidationException(cert); + BOOST_THROW_EXCEPTION(LLCertBasicConstraintsValidationException(cert)); } } } @@ -1018,7 +1019,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if(cert_chain->size() < 1) { - throw LLCertException(NULL, "No certs in chain"); + BOOST_THROW_EXCEPTION(LLCertException(NULL, "No certs in chain")); } iterator current_cert = cert_chain->begin(); LLSD current_cert_info; @@ -1033,11 +1034,11 @@ void LLBasicCertificateStore::validate(int validation_policy, (*current_cert)->getLLSD(current_cert_info); if(!validation_params.has(CERT_HOSTNAME)) { - throw LLCertException((*current_cert), "No hostname passed in for validation"); + BOOST_THROW_EXCEPTION(LLCertException((*current_cert), "No hostname passed in for validation")); } if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info[CERT_SUBJECT_NAME].has(CERT_NAME_CN)) { - throw LLInvalidCertificate((*current_cert)); + BOOST_THROW_EXCEPTION(LLInvalidCertificate((*current_cert))); } LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() << @@ -1054,7 +1055,7 @@ void LLBasicCertificateStore::validate(int validation_policy, X509* cert_x509 = (*current_cert)->getOpenSSLX509(); if(!cert_x509) { - throw LLInvalidCertificate((*current_cert)); + BOOST_THROW_EXCEPTION(LLInvalidCertificate((*current_cert))); } std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH); X509_free( cert_x509 ); @@ -1075,7 +1076,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if((validation_date < cache_entry->second.first) || (validation_date > cache_entry->second.second)) { - throw LLCertValidationExpirationException((*current_cert), validation_date); + BOOST_THROW_EXCEPTION(LLCertValidationExpirationException((*current_cert), validation_date)); } } // successfully found in cache @@ -1107,7 +1108,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if(!_verify_signature((*current_cert), previous_cert)) { - throw LLCertValidationInvalidSignatureException(previous_cert); + BOOST_THROW_EXCEPTION(LLCertValidationInvalidSignatureException(previous_cert)); } } _validateCert(local_validation_policy, @@ -1156,7 +1157,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if(!_verify_signature((*found_store_cert), (*current_cert))) { - throw LLCertValidationInvalidSignatureException(*current_cert); + BOOST_THROW_EXCEPTION(LLCertValidationInvalidSignatureException(*current_cert)); } // successfully validated. mTrustedCertCache[sha1_hash] = std::pair(from_time, to_time); @@ -1173,7 +1174,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if (validation_policy & VALIDATION_POLICY_TRUSTED) { // we reached the end without finding a trusted cert. - throw LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]); + BOOST_THROW_EXCEPTION(LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1])); } mTrustedCertCache[sha1_hash] = std::pair(from_time, to_time); @@ -1261,7 +1262,7 @@ void LLSecAPIBasicHandler::_readProtectedData() protected_data_stream.read((char *)salt, STORE_SALT_SIZE); if (protected_data_stream.gcount() < STORE_SALT_SIZE) { - throw LLProtectedDataException("Config file too short."); + BOOST_THROW_EXCEPTION(LLProtectedDataException("Config file too short.")); } cipher.decrypt(salt, STORE_SALT_SIZE); @@ -1301,7 +1302,7 @@ void LLSecAPIBasicHandler::_readProtectedData() if (parser->parse(parse_stream, mProtectedDataMap, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) { - throw LLProtectedDataException("Config file cannot be decrypted."); + BOOST_THROW_EXCEPTION(LLProtectedDataException("Config file cannot be decrypted.")); } } } @@ -1372,7 +1373,7 @@ void LLSecAPIBasicHandler::_writeProtectedData() // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() // Decided throwing an exception here was overkill until we figure out why this happens - //throw LLProtectedDataException("Error writing Protected Data Store"); + //BOOST_THROW_EXCEPTION(LLProtectedDataException("Error writing Protected Data Store")); } try @@ -1387,7 +1388,7 @@ void LLSecAPIBasicHandler::_writeProtectedData() // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() // Decided throwing an exception here was overkill until we figure out why this happens - //throw LLProtectedDataException("Could not overwrite protected data store"); + //BOOST_THROW_EXCEPTION(LLProtectedDataException("Could not overwrite protected data store")); } } catch (...) @@ -1401,7 +1402,7 @@ void LLSecAPIBasicHandler::_writeProtectedData() //crash in LLSecAPIBasicHandler::_writeProtectedData() // Decided throwing an exception here was overkill until we figure out why this happens - //throw LLProtectedDataException("Error writing Protected Data Store"); + //BOOST_THROW_EXCEPTION(LLProtectedDataException("Error writing Protected Data Store")); } } diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 382689afa0..cd4b108c1a 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -27,9 +27,10 @@ #include "llupdatedownloader.h" #include "httpcommon.h" -#include +#include "llexception.h" #include #include +#include #include #include "lldir.h" #include "llevents.h" @@ -85,11 +86,11 @@ private: namespace { class DownloadError: - public std::runtime_error + public LLException { public: DownloadError(const char * message): - std::runtime_error(message) + LLException(message) { ; // No op. } @@ -467,7 +468,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u if(!mCurl) { - throw DownloadError("failed to initialize curl"); + BOOST_THROW_EXCEPTION(DownloadError("failed to initialize curl")); } throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOSIGNAL, true)); throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_FOLLOWLOCATION, true)); @@ -508,7 +509,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str()); if(mHeaderList == 0) { - throw DownloadError("cannot add Range header"); + BOOST_THROW_EXCEPTION(DownloadError("cannot add Range header")); } throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPHEADER, mHeaderList)); @@ -524,7 +525,7 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std mDownloadData["hash"] = hash; mDownloadData["current_version"] = ll_get_version(); LLSD path = uri.pathArray(); - if(path.size() == 0) throw DownloadError("no file path"); + if(path.size() == 0) BOOST_THROW_EXCEPTION(DownloadError("no file path")); std::string fileName = path[path.size() - 1].asString(); std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName); mDownloadData["path"] = filePath; @@ -547,9 +548,9 @@ void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code) if(code != CURLE_OK) { const char * errorString = curl_easy_strerror(code); if(errorString != 0) { - throw DownloadError(curl_easy_strerror(code)); + BOOST_THROW_EXCEPTION(DownloadError(curl_easy_strerror(code))); } else { - throw DownloadError("unknown curl error"); + BOOST_THROW_EXCEPTION(DownloadError("unknown curl error")); } } else { ; // No op. diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp index 4432c6574e..9f9a08f590 100644 --- a/indra/viewer_components/updater/llupdateinstaller.cpp +++ b/indra/viewer_components/updater/llupdateinstaller.cpp @@ -30,17 +30,18 @@ #include "llupdateinstaller.h" #include "lldir.h" #include "llsd.h" +#include "llexception.h" #if defined(LL_WINDOWS) #pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!). #endif #include -#include +#include namespace { - struct RelocateError: public std::runtime_error + struct RelocateError: public LLException { - RelocateError(): std::runtime_error("llupdateinstaller: RelocateError") {} + RelocateError(): LLException("llupdateinstaller: RelocateError") {} }; std::string copy_to_temp(std::string const & path) @@ -48,7 +49,7 @@ namespace { std::string scriptFile = gDirUtilp->getBaseFileName(path); std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile); apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp); - if(status != APR_SUCCESS) throw RelocateError(); + if(status != APR_SUCCESS) BOOST_THROW_EXCEPTION(RelocateError()); return newPath; } diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 788955a1b2..0bdd1ede43 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -35,6 +35,7 @@ #include #include +#include #include "lldir.h" #include "llsdserialize.h" #include "llfile.h" @@ -190,8 +191,9 @@ void LLUpdaterServiceImpl::initialize(const std::string& channel, { if(mIsChecking || mIsDownloading) { - throw LLUpdaterService::UsageError("LLUpdaterService::initialize call " - "while updater is running."); + BOOST_THROW_EXCEPTION( + LLUpdaterService::UsageError("LLUpdaterService::initialize call " + "while updater is running.")); } mChannel = channel; @@ -222,8 +224,9 @@ void LLUpdaterServiceImpl::startChecking(bool install_if_ready) { if(mChannel.empty() || mVersion.empty()) { - throw LLUpdaterService::UsageError("Set params before call to " - "LLUpdaterService::startCheck()."); + BOOST_THROW_EXCEPTION( + LLUpdaterService::UsageError("Set params before call to " + "LLUpdaterService::startCheck().")); } mIsChecking = true; diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 95bbe1695c..78e8c6b290 100644 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -29,16 +29,17 @@ #include #include #include "llhasheduniqueid.h" +#include "llexception.h" class LLUpdaterServiceImpl; class LLUpdaterService { public: - class UsageError: public std::runtime_error + class UsageError: public LLException { public: - UsageError(const std::string& msg) : std::runtime_error(msg) {} + UsageError(const std::string& msg) : LLException(msg) {} }; // Name of the event pump through which update events will be delivered. -- cgit v1.2.3 From 1ed76c382e8b87bff02b6d37cf8acd7f6b1f8063 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 17 Aug 2016 10:45:06 -0400 Subject: MAINT-5011: Add llexception_test.cpp with tests (and conclusions). llexception_test.cpp is an unusual test source in that it need not be verified on every build, so its invocation in indra/llcommon/CMakeLists.txt is commented out with that remark. Its purpose is to help a developer decide what base class(es) to use for LLException, how to throw and how to catch. Our current conclusions are written up as comments in llexception_test.cpp. Added CRASH_ON_UNHANDLED_EXCEPTION() and LOG_UNHANDLED_EXCEPTION() macros to llexception.h -- macros to log __FILE__, __LINE__ and __PRETTY_FUNCTION__ of the catch site. These invoke functions in llexception.cpp so we don't need to #include llerror.h for every possible catch site. --- indra/llcommon/CMakeLists.txt | 8 +- indra/llcommon/llexception.cpp | 41 ++++ indra/llcommon/llexception.h | 27 ++- indra/llcommon/tests/llexception_test.cpp | 308 ++++++++++++++++++++++++++++++ 4 files changed, 377 insertions(+), 7 deletions(-) create mode 100644 indra/llcommon/llexception.cpp create mode 100644 indra/llcommon/tests/llexception_test.cpp (limited to 'indra') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 44f45144e5..410a5819b3 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -58,6 +58,7 @@ set(llcommon_SOURCE_FILES lleventfilter.cpp llevents.cpp lleventtimer.cpp + llexception.cpp llfasttimer.cpp llfile.cpp llfindlocale.cpp @@ -316,7 +317,7 @@ if (LL_TESTS) LL_ADD_INTEGRATION_TEST(llprocinfo "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") - LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lltrace "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}") @@ -329,6 +330,11 @@ if (LL_TESTS) LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}") +## llexception_test.cpp isn't a regression test, and doesn't need to be run +## every build. It's to help a developer make implementation choices about +## throwing and catching exceptions. +##LL_ADD_INTEGRATION_TEST(llexception "" "${test_libs}") + # *TODO - reenable these once tcmalloc libs no longer break the build. #ADD_BUILD_TEST(llallocator llcommon) #ADD_BUILD_TEST(llallocator_heap_profile llcommon) diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp new file mode 100644 index 0000000000..f48509b2aa --- /dev/null +++ b/indra/llcommon/llexception.cpp @@ -0,0 +1,41 @@ +/** + * @file llexception.cpp + * @author Nat Goodspeed + * @date 2016-08-12 + * @brief Implementation for llexception. + * + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llexception.h" +// STL headers +// std headers +#include +// external library headers +#include +// other Linden headers +#include "llerror.h" + +void crash_on_unhandled_exception_(const char* file, int line, const char* pretty_function) +{ + // LL_ERRS() terminates, but also propagates message into crash dump. + LL_ERRS() << file << "(" << line << "): Unhandled exception caught in " << pretty_function + << ":\n" << boost::current_exception_diagnostic_information() << LL_ENDL; +} + +void log_unhandled_exception_(const char* file, int line, const char* pretty_function, + const LLContinueError& e) +{ + // Use LL_WARNS() because we seriously do not expect this to happen + // routinely, but we DO expect to return from this function. Deriving your + // exception from LLContinueError implies that such an exception should + // NOT be fatal to the viewer, only to its current task. + LL_WARNS() << file << "(" << line << "): Unhandled " << typeid(e).name() + << " exception caught in " << pretty_function + << ":\n" << boost::current_exception_diagnostic_information() << LL_ENDL; +} diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h index 3ac2f4762f..68bd20fbcd 100644 --- a/indra/llcommon/llexception.h +++ b/indra/llcommon/llexception.h @@ -15,15 +15,20 @@ #include #include +// "Found someone who can comfort me +// But there are always exceptions..." +// - Empty Pages, Traffic, from John Barleycorn (1970) +// https://www.youtube.com/watch?v=dRH0CGVK7ic + /** * LLException is intended as the common base class from which all - * viewer-specific exceptions are derived. It is itself a subclass of - * boost::exception; use catch (const boost::exception& e) clause to log the - * string from boost::diagnostic_information(e). + * viewer-specific exceptions are derived. Rationale for why it's derived from + * both std::exception and boost::exception is explained in + * tests/llexception_test.cpp. * - * Since it is also derived from std::exception, a generic catch (const - * std::exception&) should also work, though what() is unlikely to be as - * informative as boost::diagnostic_information(). + * boost::current_exception_diagnostic_information() is quite wonderful: if + * all we need to do with an exception is log it, in most places we should + * catch (...) and log boost::current_exception_diagnostic_information(). * * Please use BOOST_THROW_EXCEPTION() * http://www.boost.org/doc/libs/release/libs/exception/doc/BOOST_THROW_EXCEPTION.html @@ -60,4 +65,14 @@ struct LLContinueError: public LLException {} }; +/// Call this macro from a catch (...) clause +#define CRASH_ON_UNHANDLED_EXCEPTION() \ + crash_on_unhandled_exception_(__FILE__, __LINE__, __PRETTY_FUNCTION__) +void crash_on_unhandled_exception_(const char*, int, const char*); + +/// Call this from a catch (const LLContinueError&) clause +#define LOG_UNHANDLED_EXCEPTION(EXC) \ + log_unhandled_exception_(__FILE__, __LINE__, __PRETTY_FUNCTION__, EXC) +void log_unhandled_exception_(const char*, int, const char*, const LLContinueError&); + #endif /* ! defined(LL_LLEXCEPTION_H) */ diff --git a/indra/llcommon/tests/llexception_test.cpp b/indra/llcommon/tests/llexception_test.cpp new file mode 100644 index 0000000000..6bee1943c2 --- /dev/null +++ b/indra/llcommon/tests/llexception_test.cpp @@ -0,0 +1,308 @@ +/** + * @file llexception_test.cpp + * @author Nat Goodspeed + * @date 2016-08-12 + * @brief Tests for throwing exceptions. + * + * This isn't a regression test: it doesn't need to be run every build, which + * is why the corresponding line in llcommon/CMakeLists.txt is commented out. + * Rather it's a head-to-head test of what kind of exception information we + * can collect from various combinations of exception base classes, type of + * throw verb and sequences of catch clauses. + * + * This "test" makes no ensure() calls: its output goes to stdout for human + * examination. + * + * As of 2016-08-12 with Boost 1.57, we come to the following conclusions. + * These should probably be re-examined from time to time as we update Boost. + * + * - It is indisputably beneficial to use BOOST_THROW_EXCEPTION() rather than + * plain throw. The macro annotates the exception object with the filename, + * line number and function name from which the exception was thrown. + * + * - That being the case, deriving only from boost::exception isn't an option. + * Every exception object passed to BOOST_THROW_EXCEPTION() must be derived + * directly or indirectly from std::exception. The only question is whether + * to also derive from boost::exception. We decided to derive LLException + * from both, as it makes message output slightly cleaner, but this is a + * trivial reason: if a strong reason emerges to prefer single inheritance, + * dropping the boost::exception base class shouldn't be a problem. + * + * - (As you will have guessed, ridiculous things like a char* or int or a + * class derived from neither boost::exception nor std::exception can only + * be caught by that specific type or (...), and + * boost::current_exception_diagnostic_information() simply throws up its + * hands and confesses utter ignorance. Stay away from such nonsense.) + * + * - But if you derive from std::exception, to nat's surprise, + * boost::current_exception_diagnostic_information() gives as much + * information about exceptions in a catch (...) clause as you can get from + * a specific catch (const std::exception&) clause, notably the concrete + * exception class and the what() string. So instead of a sequence like + * + * try { ... } + * catch (const boost::exception& e) { ... boost-flavored logging ... } + * catch (const std::exception& e) { ... std::exception logging ... } + * catch (...) { ... generic logging ... } + * + * we should be able to get away with only a catch (...) clause that logs + * boost::current_exception_diagnostic_information(). + * + * - Going further: boost::current_exception_diagnostic_information() provides + * just as much information even within a std::set_terminate() handler. So + * it might not even be strictly necessary to include a catch (...) clause + * since the viewer does use std::set_terminate(). + * + * - (We might consider adding a catch (int) clause because Kakadu internally + * throws ints, and who knows if one of those might leak out. If it does, + * boost::current_exception_diagnostic_information() can do nothing with it. + * A catch (int) clause could at least log the value and rethrow.) + * + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llexception.h" +// STL headers +// std headers +#include +// external library headers +#include +// other Linden headers +#include "../test/lltut.h" + +// helper for display output +// usage: std::cout << center(some string value, fill char, width) << std::endl; +// (assumes it's the only thing on that particular line) +struct center +{ + center(const std::string& label, char fill, std::size_t width): + mLabel(label), + mFill(fill), + mWidth(width) + {} + + // Use friend declaration not because we need to grant access, but because + // it lets us declare a free operator like a member function. + friend std::ostream& operator<<(std::ostream& out, const center& ctr) + { + std::size_t padded = ctr.mLabel.length() + 2; + std::size_t left = (ctr.mWidth - padded) / 2; + std::size_t right = ctr.mWidth - left - padded; + return out << std::string(left, ctr.mFill) << ' ' << ctr.mLabel << ' ' + << std::string(right, ctr.mFill); + } + + std::string mLabel; + char mFill; + std::size_t mWidth; +}; + +/***************************************************************************** +* Four kinds of exceptions: derived from boost::exception, from +* std::exception, from both, from neither +*****************************************************************************/ +// Interestingly, we can't use this variant with BOOST_THROW_EXCEPTION() +// (which we want) -- we reach a failure topped by this comment: +// //All boost exceptions are required to derive from std::exception, +// //to ensure compatibility with BOOST_NO_EXCEPTIONS. +struct FromBoost: public boost::exception +{ + FromBoost(const std::string& what): mWhat(what) {} + ~FromBoost() throw() {} + std::string what() const { return mWhat; } + std::string mWhat; +}; + +struct FromStd: public std::runtime_error +{ + FromStd(const std::string& what): std::runtime_error(what) {} +}; + +struct FromBoth: public boost::exception, public std::runtime_error +{ + FromBoth(const std::string& what): std::runtime_error(what) {} +}; + +// Same deal with FromNeither: can't use with BOOST_THROW_EXCEPTION(). +struct FromNeither +{ + FromNeither(const std::string& what): mWhat(what) {} + std::string what() const { return mWhat; } + std::string mWhat; +}; + +/***************************************************************************** +* Two kinds of throws: plain throw and BOOST_THROW_EXCEPTION() +*****************************************************************************/ +template +void plain_throw(const std::string& what) +{ + throw EXC(what); +} + +template +void boost_throw(const std::string& what) +{ + BOOST_THROW_EXCEPTION(EXC(what)); +} + +// Okay, for completeness, functions that throw non-class values. We wouldn't +// even deign to consider these if we hadn't found examples in our own source +// code! (Note that Kakadu's internal exception support is still based on +// throwing ints.) +void throw_char_ptr(const std::string& what) +{ + throw what.c_str(); // umm... +} + +void throw_int(const std::string& what) +{ + throw int(what.length()); +} + +/***************************************************************************** +* Three sequences of catch clauses: +* boost::exception then ..., +* std::exception then ..., +* or just ... +*****************************************************************************/ +void catch_boost_dotdotdot(void (*thrower)(const std::string&), const std::string& what) +{ + try + { + thrower(what); + } + catch (const boost::exception& e) + { + std::cout << "catch (const boost::exception& e)" << std::endl; + std::cout << "e is " << typeid(e).name() << std::endl; + std::cout << "boost::diagnostic_information(e):\n'" + << boost::diagnostic_information(e) << "'" << std::endl; + // no way to report e.what() + } + catch (...) + { + std::cout << "catch (...)" << std::endl; + std::cout << "boost::current_exception_diagnostic_information():\n'" + << boost::current_exception_diagnostic_information() << "'" + << std::endl; + } +} + +void catch_std_dotdotdot(void (*thrower)(const std::string&), const std::string& what) +{ + try + { + thrower(what); + } + catch (const std::exception& e) + { + std::cout << "catch (const std::exception& e)" << std::endl; + std::cout << "e is " << typeid(e).name() << std::endl; + std::cout << "boost::diagnostic_information(e):\n'" + << boost::diagnostic_information(e) << "'" << std::endl; + std::cout << "e.what: '" + << e.what() << "'" << std::endl; + } + catch (...) + { + std::cout << "catch (...)" << std::endl; + std::cout << "boost::current_exception_diagnostic_information():\n'" + << boost::current_exception_diagnostic_information() << "'" + << std::endl; + } +} + +void catch_dotdotdot(void (*thrower)(const std::string&), const std::string& what) +{ + try + { + thrower(what); + } + catch (...) + { + std::cout << "catch (...)" << std::endl; + std::cout << "boost::current_exception_diagnostic_information():\n'" + << boost::current_exception_diagnostic_information() << "'" + << std::endl; + } +} + +/***************************************************************************** +* Try a particular kind of throw against each of three catch sequences +*****************************************************************************/ +void catch_several(void (*thrower)(const std::string&), const std::string& what) +{ + std::cout << std::string(20, '-') << "catch_boost_dotdotdot(" << what << ")" << std::endl; + catch_boost_dotdotdot(thrower, "catch_boost_dotdotdot(" + what + ")"); + + std::cout << std::string(20, '-') << "catch_std_dotdotdot(" << what << ")" << std::endl; + catch_std_dotdotdot(thrower, "catch_std_dotdotdot(" + what + ")"); + + std::cout << std::string(20, '-') << "catch_dotdotdot(" << what << ")" << std::endl; + catch_dotdotdot(thrower, "catch_dotdotdot(" + what + ")"); +} + +/***************************************************************************** +* For a particular kind of exception, try both kinds of throw against all +* three catch sequences +*****************************************************************************/ +template +void catch_both_several(const std::string& what) +{ + std::cout << std::string(20, '*') << "plain_throw<" << what << ">" << std::endl; + catch_several(plain_throw, "plain_throw<" + what + ">"); + + std::cout << std::string(20, '*') << "boost_throw<" << what << ">" << std::endl; + catch_several(boost_throw, "boost_throw<" + what + ">"); +} + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct llexception_data + { + }; + typedef test_group llexception_group; + typedef llexception_group::object object; + llexception_group llexceptiongrp("llexception"); + + template<> template<> + void object::test<1>() + { + set_test_name("throwing exceptions"); + + // For each kind of exception, try both kinds of throw against all + // three catch sequences + std::size_t margin = 72; + std::cout << center("FromStd", '=', margin) << std::endl; + catch_both_several("FromStd"); + + std::cout << center("FromBoth", '=', margin) << std::endl; + catch_both_several("FromBoth"); + + std::cout << center("FromBoost", '=', margin) << std::endl; + // can't throw with BOOST_THROW_EXCEPTION(), just use catch_several() + catch_several(plain_throw, "plain_throw"); + + std::cout << center("FromNeither", '=', margin) << std::endl; + // can't throw this with BOOST_THROW_EXCEPTION() either + catch_several(plain_throw, "plain_throw"); + + std::cout << center("const char*", '=', margin) << std::endl; + // We don't expect BOOST_THROW_EXCEPTION() to throw anything so daft + // as a const char* or an int, so don't bother with + // catch_both_several() -- just catch_several(). + catch_several(throw_char_ptr, "throw_char_ptr"); + + std::cout << center("int", '=', margin) << std::endl; + catch_several(throw_int, "throw_int"); + } +} // namespace tut -- cgit v1.2.3 From 5e9d2f57c82a57307a48afea09aa539b9fa80abf Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 17 Aug 2016 11:36:24 -0400 Subject: MAINT-5011: Use LLTHROW() instead of plain BOOST_THROW_EXCEPTION(). A level of preprocessor indirection lets us later change the implementation if desired. --- indra/llcommon/lldependencies.cpp | 4 +- indra/llcommon/lleventcoro.cpp | 4 +- indra/llcommon/llevents.cpp | 18 ++++---- indra/llcommon/llexception.h | 16 ++++--- indra/llcommon/llleap.cpp | 6 +-- indra/llcommon/llprocess.cpp | 20 ++++---- indra/llcommon/llthreadsafequeue.cpp | 14 +++--- indra/llcommon/lluuid.cpp | 2 +- indra/llcommon/tests/wrapllerrs.h | 3 +- indra/llimage/llpngwrapper.cpp | 9 ++-- indra/llkdu/llimagej2ckdu.cpp | 3 +- indra/llmessage/llhttpnode.cpp | 9 ++-- indra/llmessage/tests/commtest.h | 3 +- indra/llmessage/tests/networkio.h | 5 +- indra/newview/llappviewer.cpp | 3 +- indra/newview/llcommandlineparser.cpp | 17 ++++--- indra/newview/llsecapi.cpp | 4 +- indra/newview/llsechandler_basic.cpp | 54 +++++++++++----------- .../updater/llupdatedownloader.cpp | 11 ++--- .../updater/llupdateinstaller.cpp | 3 +- .../viewer_components/updater/llupdaterservice.cpp | 12 ++--- 21 files changed, 104 insertions(+), 116 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/lldependencies.cpp b/indra/llcommon/lldependencies.cpp index 87a699ff14..0d5757effd 100644 --- a/indra/llcommon/lldependencies.cpp +++ b/indra/llcommon/lldependencies.cpp @@ -39,8 +39,8 @@ #include #include #include -#include // other Linden headers +#include "llexception.h" LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const { @@ -77,7 +77,7 @@ LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const // Omit independent nodes: display only those that might contribute to // the cycle. describe(out, false); - BOOST_THROW_EXCEPTION(Cycle(out.str())); + LLTHROW(Cycle(out.str())); } // A peculiarity of boost::topological_sort() is that it emits results in // REVERSE topological order: to get the result you want, you must diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index f444530a17..56367b8f54 100644 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp @@ -34,12 +34,12 @@ #include // std headers // external library headers -#include // other Linden headers #include "llsdserialize.h" #include "llerror.h" #include "llcoros.h" #include "llmake.h" +#include "llexception.h" #include "lleventfilter.h" @@ -352,7 +352,7 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc) // returning it, deliver it via exception. if (result.second) { - BOOST_THROW_EXCEPTION(LLErrorEvent(desc, result.first)); + LLTHROW(LLErrorEvent(desc, result.first)); } // That way, our caller knows a simple return must be from the reply // pump (pump 0). diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 50919edb8e..19d700a3b0 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -45,7 +45,6 @@ #include // external library headers #include -#include #if LL_WINDOWS #pragma warning (push) #pragma warning (disable : 4701) // compiler thinks might use uninitialized var, but no @@ -58,6 +57,7 @@ #include "stringize.h" #include "llerror.h" #include "llsdutil.h" +#include "llexception.h" #if LL_MSVC #pragma warning (disable : 4702) #endif @@ -175,7 +175,7 @@ std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string // Unless we're permitted to tweak it, that's Bad. if (! tweak) { - BOOST_THROW_EXCEPTION(LLEventPump::DupPumpName(std::string("Duplicate LLEventPump name '") + name + "'")); + LLTHROW(LLEventPump::DupPumpName("Duplicate LLEventPump name '" + name + "'")); } // The passed name isn't unique, but we're permitted to tweak it. Find the // first decimal-integer suffix not already taken. The insert() attempt @@ -327,9 +327,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL // is only when the existing connection object is still connected. if (found != mConnections.end() && found->second.connected()) { - BOOST_THROW_EXCEPTION( - DupListenerName(std::string("Attempt to register duplicate listener name '") + name + - "' on " + typeid(*this).name() + " '" + getName() + "'")); + LLTHROW(DupListenerName("Attempt to register duplicate listener name '" + name + + "' on " + typeid(*this).name() + " '" + getName() + "'")); } // Okay, name is unique, try to reconcile its dependencies. Specify a new // "node" value that we never use for an mSignal placement; we'll fix it @@ -355,9 +354,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL // unsortable. If we leave the new node in mDeps, it will continue // to screw up all future attempts to sort()! Pull it out. mDeps.remove(name); - BOOST_THROW_EXCEPTION( - Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() + - " '" + getName() + "' would cause cycle: " + e.what())); + LLTHROW(Cycle("New listener '" + name + "' on " + typeid(*this).name() + + " '" + getName() + "' would cause cycle: " + e.what())); } // Walk the list to verify that we haven't changed the order. float previous = 0.0, myprev = 0.0; @@ -421,7 +419,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL // NOW remove the offending listener node. mDeps.remove(name); // Having constructed a description of the order change, inform caller. - BOOST_THROW_EXCEPTION(OrderChange(out.str())); + LLTHROW(OrderChange(out.str())); } // This node becomes the previous one. previous = dmi->second; @@ -611,7 +609,7 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const { if (! mListener) { - BOOST_THROW_EXCEPTION(Empty("attempting to call uninitialized")); + LLTHROW(Empty("attempting to call uninitialized")); } return (*mListener)(event); } diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h index 68bd20fbcd..e9e25ae689 100644 --- a/indra/llcommon/llexception.h +++ b/indra/llcommon/llexception.h @@ -14,6 +14,7 @@ #include #include +#include // "Found someone who can comfort me // But there are always exceptions..." @@ -30,12 +31,6 @@ * all we need to do with an exception is log it, in most places we should * catch (...) and log boost::current_exception_diagnostic_information(). * - * Please use BOOST_THROW_EXCEPTION() - * http://www.boost.org/doc/libs/release/libs/exception/doc/BOOST_THROW_EXCEPTION.html - * to throw viewer exceptions whenever possible. This enriches the exception's - * diagnostic_information() with the source file, line and containing function - * of the BOOST_THROW_EXCEPTION() macro. - * * There may be circumstances in which it would be valuable to distinguish an * exception explicitly thrown by viewer code from an exception thrown by * (say) a third-party library. Catching (const LLException&) supports such @@ -65,6 +60,15 @@ struct LLContinueError: public LLException {} }; +/** + * Please use LLTHROW() to throw viewer exceptions whenever possible. This + * enriches the exception's diagnostic_information() with the source file, + * line and containing function of the LLTHROW() macro. + */ +// Currently we implement that using BOOST_THROW_EXCEPTION(). Wrap it in +// LLTHROW() in case we ever want to revisit that implementation decision. +#define LLTHROW(x) BOOST_THROW_EXCEPTION(x) + /// Call this macro from a catch (...) clause #define CRASH_ON_UNHANDLED_EXCEPTION() \ crash_on_unhandled_exception_(__FILE__, __LINE__, __PRETTY_FUNCTION__) diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index a8bb9bc53a..c87d2a3e58 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -21,7 +21,6 @@ #include #include #include -#include // other Linden headers #include "llerror.h" #include "llstring.h" @@ -34,6 +33,7 @@ #include "lltimer.h" #include "lluuid.h" #include "llleaplistener.h" +#include "llexception.h" #if LL_MSVC #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally @@ -70,7 +70,7 @@ public: // Rule out empty vector if (plugin.empty()) { - BOOST_THROW_EXCEPTION(Error("no plugin command")); + LLTHROW(Error("no plugin command")); } // Don't leave desc empty either, but in this case, if we weren't @@ -113,7 +113,7 @@ public: // If that didn't work, no point in keeping this LLLeap object. if (! mChild) { - BOOST_THROW_EXCEPTION(Error(STRINGIZE("failed to run " << mDesc))); + LLTHROW(Error(STRINGIZE("failed to run " << mDesc))); } // Okay, launch apparently worked. Change our mDonePump listener. diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index ca19c94736..8c321d06b9 100644 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -34,12 +34,12 @@ #include "llapr.h" #include "apr_signal.h" #include "llevents.h" +#include "llexception.h" #include #include #include #include -#include #include #include #include @@ -531,9 +531,8 @@ LLProcess::LLProcess(const LLSDOrParams& params): if (! params.validateBlock(true)) { - BOOST_THROW_EXCEPTION( - LLProcessError(STRINGIZE("not launched: failed parameter validation\n" - << LLSDNotationStreamer(params)))); + LLTHROW(LLProcessError(STRINGIZE("not launched: failed parameter validation\n" + << LLSDNotationStreamer(params)))); } mPostend = params.postend; @@ -598,11 +597,10 @@ LLProcess::LLProcess(const LLSDOrParams& params): } else { - BOOST_THROW_EXCEPTION( - LLProcessError(STRINGIZE("For " << params.executable() - << ": unsupported FileParam for " << which - << ": type='" << fparam.type() - << "', name='" << fparam.name() << "'"))); + LLTHROW(LLProcessError(STRINGIZE("For " << params.executable() + << ": unsupported FileParam for " << which + << ": type='" << fparam.type() + << "', name='" << fparam.name() << "'"))); } } // By default, pass APR_NO_PIPE for unspecified slots. @@ -681,7 +679,7 @@ LLProcess::LLProcess(const LLSDOrParams& params): if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr, gAPRPoolp))) { - BOOST_THROW_EXCEPTION(LLProcessError(STRINGIZE(params << " failed"))); + LLTHROW(LLProcessError(STRINGIZE(params << " failed"))); } // arrange to call status_callback() @@ -1066,7 +1064,7 @@ PIPETYPE& LLProcess::getPipe(FILESLOT slot) PIPETYPE* wp = getPipePtr(error, slot); if (! wp) { - BOOST_THROW_EXCEPTION(NoPipe(error)); + LLTHROW(NoPipe(error)); } return *wp; } diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp index a004618e96..491f920c0f 100644 --- a/indra/llcommon/llthreadsafequeue.cpp +++ b/indra/llcommon/llthreadsafequeue.cpp @@ -26,8 +26,8 @@ #include "linden_common.h" #include #include -#include #include "llthreadsafequeue.h" +#include "llexception.h" @@ -42,13 +42,13 @@ LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * po { if(mOwnsPool) { apr_status_t status = apr_pool_create(&mPool, 0); - if(status != APR_SUCCESS) BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("failed to allocate pool")); + if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate pool")); } else { ; // No op. } apr_status_t status = apr_queue_create(&mQueue, capacity, mPool); - if(status != APR_SUCCESS) BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("failed to allocate queue")); + if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate queue")); } @@ -69,9 +69,9 @@ void LLThreadSafeQueueImplementation::pushFront(void * element) apr_status_t status = apr_queue_push(mQueue, element); if(status == APR_EINTR) { - BOOST_THROW_EXCEPTION(LLThreadSafeQueueInterrupt()); + LLTHROW(LLThreadSafeQueueInterrupt()); } else if(status != APR_SUCCESS) { - BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("push failed")); + LLTHROW(LLThreadSafeQueueError("push failed")); } else { ; // Success. } @@ -89,9 +89,9 @@ void * LLThreadSafeQueueImplementation::popBack(void) apr_status_t status = apr_queue_pop(mQueue, &element); if(status == APR_EINTR) { - BOOST_THROW_EXCEPTION(LLThreadSafeQueueInterrupt()); + LLTHROW(LLThreadSafeQueueInterrupt()); } else if(status != APR_SUCCESS) { - BOOST_THROW_EXCEPTION(LLThreadSafeQueueError("pop failed")); + LLTHROW(LLThreadSafeQueueError("pop failed")); } else { return element; } diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index 785cf47926..d4af2c6b01 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -83,7 +83,7 @@ unsigned int decode( char const * fiveChars ) throw( bad_input_data ) unsigned int ret = 0; for( int ix = 0; ix < 5; ++ix ) { char * s = strchr( encodeTable, fiveChars[ ix ] ); -if( s == 0 ) BOOST_THROW_EXCEPTION(bad_input_data()); +if( s == 0 ) LLTHROW(bad_input_data()); ret = ret * 85 + (s-encodeTable); } return ret; diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index fa16fd6915..9a4bbbd630 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -40,7 +40,6 @@ #include #include #include -#include #include #include @@ -79,7 +78,7 @@ struct WrapLLErrs error = message; // Also throw an appropriate exception since calling code is likely to // assume that control won't continue beyond LL_ERRS. - BOOST_THROW_EXCEPTION(FatalException(message)); + LLTHROW(FatalException(message)); } std::string error; diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index 0b7d4c717f..640eda7b01 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -32,7 +32,6 @@ #include "llpngwrapper.h" #include "llexception.h" -#include namespace { struct PngError: public LLException @@ -88,7 +87,7 @@ BOOL LLPngWrapper::isValidPng(U8* src) // occurs. We throw PngError and let our try/catch block clean up. void LLPngWrapper::errorHandler(png_structp png_ptr, png_const_charp msg) { - BOOST_THROW_EXCEPTION(PngError(msg)); + LLTHROW(PngError(msg)); } // Called by the libpng library when reading (decoding) the PNG file. We @@ -138,7 +137,7 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf this, &errorHandler, NULL); if (mReadPngPtr == NULL) { - BOOST_THROW_EXCEPTION(PngError("Problem creating png read structure")); + LLTHROW(PngError("Problem creating png read structure")); } // Allocate/initialize the memory for image information. @@ -297,14 +296,14 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest) if (mColorType == -1) { - BOOST_THROW_EXCEPTION(PngError("Unsupported image: unexpected number of channels")); + LLTHROW(PngError("Unsupported image: unexpected number of channels")); } mWritePngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &errorHandler, NULL); if (!mWritePngPtr) { - BOOST_THROW_EXCEPTION(PngError("Problem creating png write structure")); + LLTHROW(PngError("Problem creating png write structure")); } mWriteInfoPtr = png_create_info_struct(mWritePngPtr); diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index fa58931407..8dd0b6d458 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -35,7 +35,6 @@ #include "kdu_block_coding.h" #include "llexception.h" -#include namespace { struct KDUError: public LLException @@ -181,7 +180,7 @@ void LLKDUMessageError::flush(bool end_of_message) { if (end_of_message) { - BOOST_THROW_EXCEPTION(KDUError("LLKDUMessageError::flush()")); + LLTHROW(KDUError("LLKDUMessageError::flush()")); } } diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp index 48ce258ba2..04b34a296c 100644 --- a/indra/llmessage/llhttpnode.cpp +++ b/indra/llmessage/llhttpnode.cpp @@ -32,7 +32,6 @@ #include "llstl.h" #include "llhttpconstants.h" #include "llexception.h" -#include const std::string CONTEXT_HEADERS("headers"); const std::string CONTEXT_PATH("path"); @@ -103,19 +102,19 @@ namespace { // virtual LLSD LLHTTPNode::simpleGet() const { - BOOST_THROW_EXCEPTION(NotImplemented()); + LLTHROW(NotImplemented()); } // virtual LLSD LLHTTPNode::simplePut(const LLSD& input) const { - BOOST_THROW_EXCEPTION(NotImplemented()); + LLTHROW(NotImplemented()); } // virtual LLSD LLHTTPNode::simplePost(const LLSD& input) const { - BOOST_THROW_EXCEPTION(NotImplemented()); + LLTHROW(NotImplemented()); } @@ -175,7 +174,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons // virtual LLSD LLHTTPNode::simpleDel(const LLSD&) const { - BOOST_THROW_EXCEPTION(NotImplemented()); + LLTHROW(NotImplemented()); } // virtual diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h index 5dff56b44f..7c8f27bbd2 100644 --- a/indra/llmessage/tests/commtest.h +++ b/indra/llmessage/tests/commtest.h @@ -38,7 +38,6 @@ #include #include #include -#include struct CommtestError: public LLException { @@ -69,7 +68,7 @@ static int query_port(const std::string& var) const char* cport = getenv(var.c_str()); if (! cport) { - BOOST_THROW_EXCEPTION(CommtestError(STRINGIZE("missing environment variable" << var))); + LLTHROW(CommtestError(STRINGIZE("missing environment variable" << var))); } // This will throw, too, if the value of PORT isn't numeric. int port(boost::lexical_cast(cport)); diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h index 6aaecf9bac..5eb739393f 100644 --- a/indra/llmessage/tests/networkio.h +++ b/indra/llmessage/tests/networkio.h @@ -35,7 +35,6 @@ #include "llpumpio.h" #include "llhttpclient.h" #include "llexception.h" -#include /***************************************************************************** * NetworkIO @@ -53,7 +52,7 @@ public: ll_init_apr(); if (! gAPRPoolp) { - BOOST_THROW_EXCEPTION(LLException("Can't initialize APR")); + LLTHROW(LLException("Can't initialize APR")); } // Create IO Pump to use for HTTP Requests. @@ -61,7 +60,7 @@ public: LLHTTPClient::setPump(*mServicePump); if (ll_init_ares() == NULL || !gAres->isInitialized()) { - BOOST_THROW_EXCEPTION(LLException("Can't start DNS resolver")); + LLTHROW(LLException("Can't start DNS resolver")); } // You can interrupt pump() without waiting the full timeout duration diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index fdef556589..0eca63da46 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -132,7 +132,6 @@ #include #include #include -#include #if LL_WINDOWS # include // For _SH_DENYWR in processMarkerFiles @@ -5513,7 +5512,7 @@ void LLAppViewer::forceErrorInfiniteLoop() void LLAppViewer::forceErrorSoftwareException() { LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL; - BOOST_THROW_EXCEPTION(LLException("User selected Force Software Exception")); + LLTHROW(LLException("User selected Force Software Exception")); } void LLAppViewer::forceErrorDriverCrash() diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp index 54f96b8872..90a5483dc9 100644 --- a/indra/newview/llcommandlineparser.cpp +++ b/indra/newview/llcommandlineparser.cpp @@ -43,7 +43,6 @@ #include #include #include -#include #if _MSC_VER # pragma warning(pop) @@ -52,6 +51,7 @@ #include "llsdserialize.h" #include "llerror.h" #include "stringize.h" +#include "llexception.h" #include #include #include @@ -204,17 +204,17 @@ protected: { if(gPastLastOption) { - BOOST_THROW_EXCEPTION(LLCLPLastOption("Don't parse no more!")); + LLTHROW(LLCLPLastOption("Don't parse no more!")); } // Error checks. Needed? if (!value_store.empty() && !is_composing()) { - BOOST_THROW_EXCEPTION(LLCLPError("Non composing value with multiple occurences.")); + LLTHROW(LLCLPError("Non composing value with multiple occurences.")); } if (new_tokens.size() < min_tokens() || new_tokens.size() > max_tokens()) { - BOOST_THROW_EXCEPTION(LLCLPError("Illegal number of tokens specified.")); + LLTHROW(LLCLPError("Illegal number of tokens specified.")); } if(value_store.empty()) @@ -468,7 +468,7 @@ onevalue(const std::string& option, { // What does it mean when the user specifies a command-line switch // that requires a value, but omits the value? Complain. - BOOST_THROW_EXCEPTION(LLCLPError(STRINGIZE("No value specified for --" << option << "!"))); + LLTHROW(LLCLPError(STRINGIZE("No value specified for --" << option << "!"))); } else if (value.size() > 1) { @@ -486,10 +486,9 @@ void badvalue(const std::string& option, // If the user passes an unusable value for a command-line switch, it // seems like a really bad idea to just ignore it, even with a log // warning. - BOOST_THROW_EXCEPTION( - LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option - << "' for variable '" << varname << "' of type " << type - << ": '" << value << "'"))); + LLTHROW(LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option + << "' for variable '" << varname << "' of type " << type + << ": '" << value << "'"))); } template diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index bcb9417820..933f7bb16e 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -29,7 +29,7 @@ #include "llviewerprecompiledheaders.h" #include "llsecapi.h" #include "llsechandler_basic.h" -#include +#include "llexception.h" #include #include #include @@ -70,7 +70,7 @@ void initializeSecHandler() } if (!exception_msg.empty()) // an exception was thrown. { - BOOST_THROW_EXCEPTION(LLProtectedDataException(exception_msg)); + LLTHROW(LLProtectedDataException(exception_msg)); } } diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 39ce64ad0e..183a625382 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -35,7 +35,7 @@ #include "llfile.h" #include "lldir.h" #include "llviewercontrol.h" -#include +#include "llexception.h" #include #include #include @@ -73,14 +73,14 @@ LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert) if(pem_bio == NULL) { LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL; - BOOST_THROW_EXCEPTION(LLInvalidCertificate(this)); + LLTHROW(LLInvalidCertificate(this)); } mCert = NULL; PEM_read_bio_X509(pem_bio, &mCert, 0, NULL); BIO_free(pem_bio); if (!mCert) { - BOOST_THROW_EXCEPTION(LLInvalidCertificate(this)); + LLTHROW(LLInvalidCertificate(this)); } } @@ -89,7 +89,7 @@ LLBasicCertificate::LLBasicCertificate(X509* pCert) { if (!pCert || !pCert->cert_info) { - BOOST_THROW_EXCEPTION(LLInvalidCertificate(this)); + LLTHROW(LLInvalidCertificate(this)); } mCert = X509_dup(pCert); } @@ -874,22 +874,22 @@ void _validateCert(int validation_policy, // check basic properties exist in the cert if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info.has(CERT_SUBJECT_NAME_STRING)) { - BOOST_THROW_EXCEPTION(LLCertException(cert, "Cert doesn't have a Subject Name")); + LLTHROW(LLCertException(cert, "Cert doesn't have a Subject Name")); } if(!current_cert_info.has(CERT_ISSUER_NAME_STRING)) { - BOOST_THROW_EXCEPTION(LLCertException(cert, "Cert doesn't have an Issuer Name")); + LLTHROW(LLCertException(cert, "Cert doesn't have an Issuer Name")); } // check basic properties exist in the cert if(!current_cert_info.has(CERT_VALID_FROM) || !current_cert_info.has(CERT_VALID_TO)) { - BOOST_THROW_EXCEPTION(LLCertException(cert, "Cert doesn't have an expiration period")); + LLTHROW(LLCertException(cert, "Cert doesn't have an expiration period")); } if (!current_cert_info.has(CERT_SHA1_DIGEST)) { - BOOST_THROW_EXCEPTION(LLCertException(cert, "No SHA1 digest")); + LLTHROW(LLCertException(cert, "No SHA1 digest")); } if (validation_policy & VALIDATION_POLICY_TIME) @@ -904,7 +904,7 @@ void _validateCert(int validation_policy, if((validation_date < current_cert_info[CERT_VALID_FROM].asDate()) || (validation_date > current_cert_info[CERT_VALID_TO].asDate())) { - BOOST_THROW_EXCEPTION(LLCertValidationExpirationException(cert, validation_date)); + LLTHROW(LLCertValidationExpirationException(cert, validation_date)); } } if (validation_policy & VALIDATION_POLICY_SSL_KU) @@ -915,14 +915,14 @@ void _validateCert(int validation_policy, !(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE], LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT))))) { - BOOST_THROW_EXCEPTION(LLCertKeyUsageValidationException(cert)); + LLTHROW(LLCertKeyUsageValidationException(cert)); } // only validate EKU if the cert has it if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE) && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray() && (!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE], LLSD((std::string)CERT_EKU_SERVER_AUTH)))) { - BOOST_THROW_EXCEPTION(LLCertKeyUsageValidationException(cert)); + LLTHROW(LLCertKeyUsageValidationException(cert)); } } if (validation_policy & VALIDATION_POLICY_CA_KU) @@ -931,7 +931,7 @@ void _validateCert(int validation_policy, (!_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE], (std::string)CERT_KU_CERT_SIGN))) { - BOOST_THROW_EXCEPTION(LLCertKeyUsageValidationException(cert)); + LLTHROW(LLCertKeyUsageValidationException(cert)); } } @@ -943,13 +943,13 @@ void _validateCert(int validation_policy, if(!current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_CA) || !current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_CA]) { - BOOST_THROW_EXCEPTION(LLCertBasicConstraintsValidationException(cert)); + LLTHROW(LLCertBasicConstraintsValidationException(cert)); } if (current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_PATHLEN) && ((current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger() != 0) && (depth > current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger()))) { - BOOST_THROW_EXCEPTION(LLCertBasicConstraintsValidationException(cert)); + LLTHROW(LLCertBasicConstraintsValidationException(cert)); } } } @@ -1019,7 +1019,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if(cert_chain->size() < 1) { - BOOST_THROW_EXCEPTION(LLCertException(NULL, "No certs in chain")); + LLTHROW(LLCertException(NULL, "No certs in chain")); } iterator current_cert = cert_chain->begin(); LLSD current_cert_info; @@ -1034,11 +1034,11 @@ void LLBasicCertificateStore::validate(int validation_policy, (*current_cert)->getLLSD(current_cert_info); if(!validation_params.has(CERT_HOSTNAME)) { - BOOST_THROW_EXCEPTION(LLCertException((*current_cert), "No hostname passed in for validation")); + LLTHROW(LLCertException((*current_cert), "No hostname passed in for validation")); } if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info[CERT_SUBJECT_NAME].has(CERT_NAME_CN)) { - BOOST_THROW_EXCEPTION(LLInvalidCertificate((*current_cert))); + LLTHROW(LLInvalidCertificate((*current_cert))); } LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() << @@ -1055,7 +1055,7 @@ void LLBasicCertificateStore::validate(int validation_policy, X509* cert_x509 = (*current_cert)->getOpenSSLX509(); if(!cert_x509) { - BOOST_THROW_EXCEPTION(LLInvalidCertificate((*current_cert))); + LLTHROW(LLInvalidCertificate((*current_cert))); } std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH); X509_free( cert_x509 ); @@ -1076,7 +1076,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if((validation_date < cache_entry->second.first) || (validation_date > cache_entry->second.second)) { - BOOST_THROW_EXCEPTION(LLCertValidationExpirationException((*current_cert), validation_date)); + LLTHROW(LLCertValidationExpirationException((*current_cert), validation_date)); } } // successfully found in cache @@ -1108,7 +1108,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if(!_verify_signature((*current_cert), previous_cert)) { - BOOST_THROW_EXCEPTION(LLCertValidationInvalidSignatureException(previous_cert)); + LLTHROW(LLCertValidationInvalidSignatureException(previous_cert)); } } _validateCert(local_validation_policy, @@ -1157,7 +1157,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if(!_verify_signature((*found_store_cert), (*current_cert))) { - BOOST_THROW_EXCEPTION(LLCertValidationInvalidSignatureException(*current_cert)); + LLTHROW(LLCertValidationInvalidSignatureException(*current_cert)); } // successfully validated. mTrustedCertCache[sha1_hash] = std::pair(from_time, to_time); @@ -1174,7 +1174,7 @@ void LLBasicCertificateStore::validate(int validation_policy, if (validation_policy & VALIDATION_POLICY_TRUSTED) { // we reached the end without finding a trusted cert. - BOOST_THROW_EXCEPTION(LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1])); + LLTHROW(LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1])); } mTrustedCertCache[sha1_hash] = std::pair(from_time, to_time); @@ -1262,7 +1262,7 @@ void LLSecAPIBasicHandler::_readProtectedData() protected_data_stream.read((char *)salt, STORE_SALT_SIZE); if (protected_data_stream.gcount() < STORE_SALT_SIZE) { - BOOST_THROW_EXCEPTION(LLProtectedDataException("Config file too short.")); + LLTHROW(LLProtectedDataException("Config file too short.")); } cipher.decrypt(salt, STORE_SALT_SIZE); @@ -1302,7 +1302,7 @@ void LLSecAPIBasicHandler::_readProtectedData() if (parser->parse(parse_stream, mProtectedDataMap, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE) { - BOOST_THROW_EXCEPTION(LLProtectedDataException("Config file cannot be decrypted.")); + LLTHROW(LLProtectedDataException("Config file cannot be decrypted.")); } } } @@ -1373,7 +1373,7 @@ void LLSecAPIBasicHandler::_writeProtectedData() // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() // Decided throwing an exception here was overkill until we figure out why this happens - //BOOST_THROW_EXCEPTION(LLProtectedDataException("Error writing Protected Data Store")); + //LLTHROW(LLProtectedDataException("Error writing Protected Data Store")); } try @@ -1388,7 +1388,7 @@ void LLSecAPIBasicHandler::_writeProtectedData() // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() // Decided throwing an exception here was overkill until we figure out why this happens - //BOOST_THROW_EXCEPTION(LLProtectedDataException("Could not overwrite protected data store")); + //LLTHROW(LLProtectedDataException("Could not overwrite protected data store")); } } catch (...) @@ -1402,7 +1402,7 @@ void LLSecAPIBasicHandler::_writeProtectedData() //crash in LLSecAPIBasicHandler::_writeProtectedData() // Decided throwing an exception here was overkill until we figure out why this happens - //BOOST_THROW_EXCEPTION(LLProtectedDataException("Error writing Protected Data Store")); + //LLTHROW(LLProtectedDataException("Error writing Protected Data Store")); } } diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index cd4b108c1a..04e0395c50 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -30,7 +30,6 @@ #include "llexception.h" #include #include -#include #include #include "lldir.h" #include "llevents.h" @@ -468,7 +467,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u if(!mCurl) { - BOOST_THROW_EXCEPTION(DownloadError("failed to initialize curl")); + LLTHROW(DownloadError("failed to initialize curl")); } throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOSIGNAL, true)); throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_FOLLOWLOCATION, true)); @@ -509,7 +508,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte) mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str()); if(mHeaderList == 0) { - BOOST_THROW_EXCEPTION(DownloadError("cannot add Range header")); + LLTHROW(DownloadError("cannot add Range header")); } throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPHEADER, mHeaderList)); @@ -525,7 +524,7 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std mDownloadData["hash"] = hash; mDownloadData["current_version"] = ll_get_version(); LLSD path = uri.pathArray(); - if(path.size() == 0) BOOST_THROW_EXCEPTION(DownloadError("no file path")); + if(path.size() == 0) LLTHROW(DownloadError("no file path")); std::string fileName = path[path.size() - 1].asString(); std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName); mDownloadData["path"] = filePath; @@ -548,9 +547,9 @@ void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code) if(code != CURLE_OK) { const char * errorString = curl_easy_strerror(code); if(errorString != 0) { - BOOST_THROW_EXCEPTION(DownloadError(curl_easy_strerror(code))); + LLTHROW(DownloadError(curl_easy_strerror(code))); } else { - BOOST_THROW_EXCEPTION(DownloadError("unknown curl error")); + LLTHROW(DownloadError("unknown curl error")); } } else { ; // No op. diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp index 9f9a08f590..1c7629da23 100644 --- a/indra/viewer_components/updater/llupdateinstaller.cpp +++ b/indra/viewer_components/updater/llupdateinstaller.cpp @@ -36,7 +36,6 @@ #pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!). #endif #include -#include namespace { struct RelocateError: public LLException @@ -49,7 +48,7 @@ namespace { std::string scriptFile = gDirUtilp->getBaseFileName(path); std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile); apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp); - if(status != APR_SUCCESS) BOOST_THROW_EXCEPTION(RelocateError()); + if(status != APR_SUCCESS) LLTHROW(RelocateError()); return newPath; } diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 0bdd1ede43..1665e41e70 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -32,10 +32,10 @@ #include "lltimer.h" #include "llupdatechecker.h" #include "llupdateinstaller.h" +#include "llexception.h" #include #include -#include #include "lldir.h" #include "llsdserialize.h" #include "llfile.h" @@ -191,9 +191,8 @@ void LLUpdaterServiceImpl::initialize(const std::string& channel, { if(mIsChecking || mIsDownloading) { - BOOST_THROW_EXCEPTION( - LLUpdaterService::UsageError("LLUpdaterService::initialize call " - "while updater is running.")); + LLTHROW(LLUpdaterService::UsageError("LLUpdaterService::initialize call " + "while updater is running.")); } mChannel = channel; @@ -224,9 +223,8 @@ void LLUpdaterServiceImpl::startChecking(bool install_if_ready) { if(mChannel.empty() || mVersion.empty()) { - BOOST_THROW_EXCEPTION( - LLUpdaterService::UsageError("Set params before call to " - "LLUpdaterService::startCheck().")); + LLTHROW(LLUpdaterService::UsageError("Set params before call to " + "LLUpdaterService::startCheck().")); } mIsChecking = true; -- cgit v1.2.3