summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2020-03-25DRTVWR-476, SL-12197: Don't throw Stopping from main coroutine.Nat Goodspeed
The new LLCoros::Stop exception is intended to terminate long-lived coroutines -- not interrupt mainstream shutdown processing. Only throw it on an explicitly-launched coroutine. Make LLCoros::getName() (used by the above test) static. As with other LLCoros methods, it might be called after the LLCoros LLSingleton instance has been deleted. Requiring the caller to call instance() implies a possible need to also call wasDeleted(). Encapsulate that nuance into a static method instead.
2020-03-25DRTVWR-476,SL-11215,SL-11216: Update to viewer-manager build 533067Nat Goodspeed
2020-03-25DRTVWR-476: Enrich LLExceptions thrown by LLTHROW() with stack trace.Nat Goodspeed
The LLTHROW() abstraction allows us to enrich the subject exception with a boost::stacktrace -- without having to propagate the boost/stacktrace.hpp header throughout the code base. To my delight, our existing use of boost::current_exception_diagnostic_information() already reports the newly added boost::stacktrace information -- we don't have to query it specifically!
2020-03-25DRTVWR-476: Add LLTHROW()/LOG_UNHANDLED_EXCEPTION() test.Nat Goodspeed
llexception_test.cpp is about discovering appropriate infrastructure to get good information from the LLTHROW() and LOG_UNHANDLED_EXCEPTION() mechanism. But we didn't before have a test that actually exercises them. Now we do.
2020-03-25DRTVWR-476: Introduce LLStacktrace, a token to stream stack trace.Nat Goodspeed
LLStacktrace has no behavior except when you stream an instance to a std::ostream. Then it reports the current traceback at that point to the ostream. This bit of indirection is intended to avoid the boost/stacktrace.hpp header from being included everywhere.
2020-03-25DRTVWR-476: Have to package libhunspell dylib now, not .a lib.Nat Goodspeed
2020-03-25DRTVWR-476: Remove diagnostics around 'SetFile -a V' commands.Nat Goodspeed
Earlier versions of macOS manifested frustrating problems in finishing the built package. Those build steps seem to have been behaving better for a few years now. Eliminate (what we fervently hope has become) a bit of ancient cruft.
2020-03-25DRTVWR-476: Introduce LLCoprocedureManager::close(). Use in tests.Nat Goodspeed
The new close(void) method simply acquires the logic from ~LLCoprocedureManager() (which now calls close()). It's useful, even if only in test programs, to be able to shut down all existing LLCoprocedurePools without having to name them individually -- and without having to destroy the LLCoprocedureManager singleton instance. Deleting an LLSingleton should be done only once per process, whereas test programs want to reset the LLCoprocedureManager after each test.
2020-03-25DRTVWR-476: Conflate LOGFAIL env var empty with completely unset.Nat Goodspeed
Sometimes it's useful to be able to temporarily override an existing LOGFAIL setting in the current environment. It's far more convenient to prepend LOGFAIL='' to a command than to 'unset LOGFAIL' as a whole separate command -- and then remember to restore its previous value.
2020-03-25DRTVWR-476: Use LLThreadSafeQueue, not boost::fibers::buffered_channel.Nat Goodspeed
We've observed buffered_channel::try_push() hanging, which seems very odd. Try our own LLThreadSafeQueue instead.
2020-03-25DRTVWR-476: Make LLThreadSafeQueue coroutine-safe as well.Nat Goodspeed
2020-03-25DRTVWR-476: Manually count items in LLCoprocedurePool's pending queue.Nat Goodspeed
Reinstate LLCoprocedureManager::countPending() and count() methods. These were removed because boost::fibers::buffered_channel has no size() method, but since all users run within a single thread, it works to increment and decrement a simple counter. Add count information and max queue size to log messages.
2020-03-25DRTVWR-476: Back out 355d9db4a59f: unroll stderr redirection.Nat Goodspeed
2020-03-25DRTVWR-476: Back out e913c05d43b6: unroll stderr redirection.Nat Goodspeed
2020-03-25DRTVWR-476: Back out e66ec842b851: unrolling stderr redirection.Nat Goodspeed
2020-03-25DRTVWR-476: Partially revert 978e09882565: undo using LLTempRedirect.Nat Goodspeed
But leave LLTempRedirect available in the code base.
2020-03-25DRTVWR-476: Don't test configuration.emptyMap().Nat Goodspeed
LLSD::emptyMap() is a factory for an empty map instance, NOT a predicate on any particular instance. In fact checking configuration.isUndefined() and testing whether the map is empty are both subsumed by (! configuration).
2020-03-25DRTVWR-476: Always clear both fields even if mOrigTarget invalid.Nat Goodspeed
2020-03-25DRTVWR-476: Make viewer_manifest.py report its own command line.Nat Goodspeed
That way, if there's a problem, a developer can rerun the same command.
2020-03-25DRTVWR-476, SL-12205: Refactor MSVC redist library copying.Nat Goodspeed
Specify all of msvcp$VER.dll, msvcr$VER.dll and vcruntime$VER.dll -- but check each of them individually, because any given VS release has only a subset of those. Add messaging to clarify what we're doing. Introduce to_staging_dirs CMake macro to cut down on redundant boilerplate: the idiom in which we use copy_if_different twice, once to the Release staging directory and once to the RelWithDebInfo staging directory, each time appending the target pathnames to third_party_targets. Replace that idiom with calls to to_staging_dirs.
2020-03-25DRTVWR-476: Annotate Mani's plea from 2009 with a suggested solution.Nat Goodspeed
However, this is not the right moment to perform that refactoring.
2020-03-25DRTVWR-476, SL-12205: Search for msvcp140.dll, not msvcr140.dllNat Goodspeed
Evidently, with VS 2017, what would have been msvcr140.dll has become vcruntime140.dll instead. msvcr140.dll is no longer a good sample DLL for which to search.
2020-03-25DRTVWR-476, SL-12205: Update to glod built with VS 2017 runtime libs.Nat Goodspeed
2020-03-25DRTVWR-476: Encapsulate dup()/dup2() fd saving as LLTempRedirect.Nat Goodspeed
2020-03-25DRTVWR-476: For VS 2017, MSVC_VERSION can be any of a range.Nat Goodspeed
Thanks NickyD.
2020-03-25DRTVWR-476: Throw some more Microsoft runtime DLLs at the viewer.Nat Goodspeed
2020-03-25DRTVWR-476: Correct runtime DLL names for VS 2017.Nat Goodspeed
2020-03-25DRTVWR-476: Update to VS 2017 versions of runtime DLLs.Nat Goodspeed
Also forget obsolete references to VS 2010 runtime DLLs.
2020-03-25DRTVWR-476: Update to slvoice build 532334Nat Goodspeed
2020-03-25DRTVWR-476: Update llviewerjoystick.cpp for updated libndofdev API.Nat Goodspeed
2020-03-25DRTVWR-476: Update libndofdev to codeticket version 532324.Nat Goodspeed
2020-03-25DRTVWR-476: Defend against late ~LLWatchdogTimeout() calls.Nat Goodspeed
LLAppViewer's heap LLWatchdogTimeout might be destroyed very late -- as late as in LLAppViewer's destructor. By that time, LLAppViewer::cleanup() has already called LLSingletonBase::deleteAll(), destroying the LLWatchdog LLSingleton instance. But LLWatchdogTimeout isa LLWatchdogEntry, and ~LLWatchdogEntry() calls stop(), and stop() tries to remove that instance from LLWatchdog, thus inadvertently resurrecting the deleted LLWatchdog. Which is pointless because the resurrected LLWatchdog has never heard of the LLWatchdogTimeout instance trying to remove itself. Defend LLWatchdogEntry::stop() against the case in which LLWatchdog has already been deleted.
2020-03-25DRTVWR-476: On Windows, dup2() et al. need <io.h>Nat Goodspeed
2020-03-25DRTVWR-476: Try to extend stderr redirection to Windows as well.Nat Goodspeed
Make the LLError::Settings LLSingleton duplicate the file handle for stderr (usually 2) on construction. Make its destructor restore the original target for that file handle. Provide a getDupStderr() method to obtain the duplicate file handle. Move Settings declaration up to the top of the file so other code can reference it. Make RecordToFile (the Recorder subclass engaged by LLError::logToFile()), instead of duplicating stderr's file handle itself, capture the duplicate stderr file handle from Settings to revert stderr redirection on destruction. Make RecordToStderr (the Recorder subclass engaged by LLError::logToStderr()) use fdopen() to create an LLFILE* targeting the duplicate file handle from Settings. Write output to that instead of to stderr so logToStderr() continues to provide output for the user instead of duplicating each line into the log file.
2020-03-25DRTVWR-476: Add diagnostic output to llviewerjoystick.cpp.Nat Goodspeed
Add ndof_dump_list() call, to enumerate available devices, when ndof_init_first() returns failure. Add "joystick" tags to existing LL_INFOS() (etc.) calls in llviewerjoystick.cpp to make it easier to enable and disable such log messages. Add a specialized operator<<() function to log the contents of an NDOF_Device struct. Add a couple LL_DEBUGS() calls for more visibility into library operations.
2020-03-25DRTVWR-476: Try to log stderr output from classic-C libraries.Nat Goodspeed
Some of the libraries we use produce log output to stderr. Such output can be informative, but is invisible unless you launch the viewer from a console. In particular, it's invisible to anyone trying to diagnose a problem by reading someone else's SecondLife.log file. Make RecordToFile -- the Recorder subclass engaged by LLError::logToFile() -- redirect STDERR_FILENO to the newly-opened log file so that any subsequent writes to stderr (or cerr, for that matter) will be captured in the log file. But first duplicate the original stderr file handle, and restore it when RecordToFile is destroyed. That way, output written to stderr during the final moments of application shutdown should still appear on (console) stderr.
2020-03-25DRTVWR-476: Add LLUniqueFile, adding RAII semantics to LLFILE*.Nat Goodspeed
LLUniqueFile wraps an LLFILE* in a move-only class that closes the wrapped LLFILE* on destruction. It provides conversion operators to permit idiomatic usage as an LLFILE* value.
2020-03-25DRTVWR-476: Use shared_ptr to manage lifespan of coprocedure queue.Nat Goodspeed
Since the consuming coroutine LLCoprocedurePool::coprocedureInvokerCoro() has been observed to outlive the LLCoprocedurePool instance that owns the CoprocQueue_t, closing that queue isn't enough to keep the coroutine from crashing at shutdown: accessing a deleted CoprocQueue_t is fatal whether or not it's been closed. Make LLCoprocedurePool store a shared_ptr to a heap CoprocQueue_t instance, and pass that shared_ptr by value to consuming coroutines. That way the CoprocQueue_t instance is guaranteed to live as long as the last interested party.
2020-03-25DRTVWR-476: Keep coroutine-local data on toplevel()'s stack frame.Nat Goodspeed
Instead of heap-allocating a CoroData instance per coroutine, storing the pointer in a ptr_map and deleting it from the ptr_map once the fiber_specific_ptr for that coroutine is cleaned up -- just declare a stack instance on the top-level stack frame, the simplest C++ lifespan management. Derive CoroData from LLInstanceTracker to detect potential name collisions and to enumerate instances. Continue registering each coroutine's CoroData instance in our fiber_specific_ptr, but use a no-op deleter function. Make ~LLCoros() directly pump the fiber scheduler a few times, instead of having a special "LLApp" listener.
2020-03-25DRTVWR-476: Back out changeset 40c0c6a8407d ("final" LLApp listener)Nat Goodspeed
2020-03-25DRTVWR-476: Pump coroutines a few more times when we start quitting.Nat Goodspeed
By the time "LLApp" listeners are notified that the app is quitting, the mainloop is no longer running. Even though those listeners do things like close work queues and inject exceptions into pending promises, any coroutines waiting on those resources must regain control before they can notice and shut down properly. Add a final "LLApp" listener that resumes ready coroutines a few more times. Make sure every other "LLApp" listener is positioned before that new one.
2020-03-25DRTVWR-476: Don't name the caught exceptionNat Goodspeed
unless we're going to reference it.
2020-03-25DRTVWR-476: Terminate long-lived coroutines to avoid shutdown crash.Nat Goodspeed
Add LLCoros::TempStatus instances around known suspension points so printActiveCoroutines() can report what each suspended coroutine is waiting for. Similarly, sprinkle checkStop() calls at known suspension points. Make LLApp::setStatus() post an event to a new LLEventPump "LLApp" with a string corresponding to the status value being set, but only until ~LLEventPumps() -- since setStatus() also gets called very late in the application's lifetime. Make postAndSuspendSetup() (used by postAndSuspend(), suspendUntilEventOn(), postAndSuspendWithTimeout(), suspendUntilEventOnWithTimeout()) add a listener on the new "LLApp" LLEventPump that pushes the new LLCoros::Stopping exception to the coroutine waiting on the LLCoros::Promise. Make it return the new LLBoundListener along with the previous one. Accordingly, make postAndSuspend() and postAndSuspendWithTimeout() store the new LLBoundListener returned by postAndSuspendSetup() in a LLTempBoundListener (as with the previous one) so it will automatically disconnect once the wait is over. Make each LLCoprocedurePool instance listen on "LLApp" with a listener that closes the queue on which new work items are dispatched. Closing the queue causes the waiting dispatch coroutine to terminate. Store the connection in an LLTempBoundListener on the LLCoprocedurePool so it will disconnect automatically on destruction. Refactor the loop in coprocedureInvokerCoro() to instantiate TempStatus around the suspending call. Change a couple spammy LL_INFOS() calls to LL_DEBUGS(). Give all logging calls in that module a "CoProcMgr" tag to make it straightforward to re-enable the LL_DEBUGS() calls as desired.
2020-03-25DRTVWR-476: Infrastructure to help manage long-lived coroutines.Nat Goodspeed
Introduce LLCoros::Stop exception, with subclasses Stopping, Stopped and Shutdown. Add LLCoros::checkStop(), intended to be called periodically by any coroutine with nontrivial lifespan. It checks the LLApp status and, unless isRunning(), throws one of these new exceptions. Make LLCoros::toplevel() catch Stop specially and log forcible coroutine termination. Now that LLApp status matters even in a test program, introduce a trivial LLTestApp subclass whose sole function is to make isRunning() true. (LLApp::setStatus() is protected: only a subclass can call it.) Add LLTestApp instances to lleventcoro_test.cpp and lllogin_test.cpp. Make LLCoros::toplevel() accept parameters by value rather than by const reference so we can continue using them even after context switches. Make private LLCoros::get_CoroData() static. Given that we've observed some coroutines living past LLCoros destruction, making the caller call LLCoros::instance() is more dangerous than encapsulating it within a static method -- since the encapsulated call can check LLCoros::wasDeleted() first and do something reasonable instead. This also eliminates the need for both a const and non-const overload. Defend LLCoros::delete_CoroData() (cleanup function for fiber_specific_ptr for CoroData, implicitly called after coroutine termination) against calls after ~LLCoros(). Add a status string to coroutine-local data, with LLCoro::setStatus(), getStatus() and RAII class TempStatus. Add an optional 'when' string argument to LLCoros::printActiveCoroutines(). Make ~LLCoros() print the coroutines still active at destruction.
2020-03-25DRTVWR-476: Mention LLApp::stepFrame() in LLAppViewer::idle()Nat Goodspeed
which performs "by hand" the same sequence of calls found in stepFrame(). Why not simply call stepFrame()? Hysterical reasons?
2020-03-25DRTVWR-476: Make ~LLEventPumps() call reset() on its way out.Nat Goodspeed
~LLEventPumps() deletes every LLEventPump instance it created itself. However, many classes themselves contain LLEventPump subclass instances. These are registered with LLEventPumps without it managing their lifespan. But LLEventPump::reset() frees the LLStandardSignal aka boost::signals2::signal instance owned by the LLEventPump, perforce disconnecting all current listeners and disabling the LLEventPump. Even though the instance still exists, if someone subsequently calls post(), nothing will happen -- which is better than control trying to reach a method of a deleted object.
2020-03-25DRTVWR-476: Defer #include "lleventtimer.h" until lleventfilter.cpp.Nat Goodspeed
2020-03-25DRTVWR-476: Update to bugsplat build 532004Nat Goodspeed
2020-03-25DRTVWR-476: Add LLEventTimer::run_every(), run_at(), run_after().Nat Goodspeed
Also add corresponding LLEventTimeout::post_every(), post_at(), post_after() methods.
2020-03-25DRTVWR-476: Eliminate static LLEventPump factory maps.Nat Goodspeed
Having a map from std::string to a factory function returning LLEventPump* is a cool idea, especially since you could statically populate such a map with string literals and little lambdas. Unfortunately, static initialization of any data is a bad idea when control can reach consuming code before that module's static data are constructed. Since LLEventPumps is already an LLSingleton, it's simple enough to make its map non-static and initialize it in the constructor. But another recent static factory-function map was introduced in llleaplistener.cpp to support the LLLeapListener::newpump() operation. That involves no LLSingletons. Introduce LLEventPumps::make(name, tweak, type) to instantiate an LLEventPump subclass of the specified type with specified (name, tweak) parameters. Instances returned by make() are owned by LLEventPumps, as with obtain(). Introduce LLEventPumps::BadType exception for when the type string isn't recognized. LLEventPumps::obtain() can then simply call make() when the specified instance name doesn't already exist. The configuration data used internally by obtain() becomes { string instance name, string subclass name }. Although this too is currently initialized in the LLEventPumps constructor, migrating it to a configuration file would now be far more straightforward than before. LLLeapListener::newpump(), too, can call LLEventPumps::make() with the caller-specified type string. This eliminates that static factory map. newpump() must catch BadType and report the error back to its invoker. Given that the LLEventPump subclass instances returned by make() are owned by LLEventPumps rather than LLLeapListener, there is no further need for the LLLeapListener::mEventPumps ptr_map, which was used only to manage lifetime. Also remove LLLeapListener's "killpump" operation since LLEventPumps provides no corresponding functionality.