Skip to content
Snippets Groups Projects
  1. Mar 25, 2020
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      DRTVWR-476: Partially revert 978e09882565: undo using LLTempRedirect. · 950204a5
      Nat Goodspeed authored
      But leave LLTempRedirect available in the code base.
      950204a5
    • Nat Goodspeed's avatar
      DRTVWR-476: Don't test configuration.emptyMap(). · 7ef10fe1
      Nat Goodspeed authored
      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).
      7ef10fe1
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      DRTVWR-476: Make viewer_manifest.py report its own command line. · 59186204
      Nat Goodspeed authored
      That way, if there's a problem, a developer can rerun the same command.
      59186204
    • Nat Goodspeed's avatar
      DRTVWR-476, SL-12205: Refactor MSVC redist library copying. · b08c44a0
      Nat Goodspeed authored
      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.
      b08c44a0
    • Nat Goodspeed's avatar
      DRTVWR-476: Annotate Mani's plea from 2009 with a suggested solution. · 71f6f43a
      Nat Goodspeed authored
      However, this is not the right moment to perform that refactoring.
      71f6f43a
    • Nat Goodspeed's avatar
      DRTVWR-476, SL-12205: Search for msvcp140.dll, not msvcr140.dll · 44b9dd2e
      Nat Goodspeed authored
      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.
      44b9dd2e
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      DRTVWR-476: For VS 2017, MSVC_VERSION can be any of a range. · 5f1140c0
      Nat Goodspeed authored
      Thanks NickyD.
      5f1140c0
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      e9ef6681
    • Nat Goodspeed's avatar
      DRTVWR-476: Update to VS 2017 versions of runtime DLLs. · 235b37bb
      Nat Goodspeed authored
      Also forget obsolete references to VS 2010 runtime DLLs.
      235b37bb
    • Nat Goodspeed's avatar
      698922e0
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      DRTVWR-476: Defend against late ~LLWatchdogTimeout() calls. · ec208ddf
      Nat Goodspeed authored
      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.
      ec208ddf
    • Nat Goodspeed's avatar
      7f1a2002
    • Nat Goodspeed's avatar
      DRTVWR-476: Try to extend stderr redirection to Windows as well. · 07134aae
      Nat Goodspeed authored
      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.
      07134aae
    • Nat Goodspeed's avatar
      DRTVWR-476: Add diagnostic output to llviewerjoystick.cpp. · f80b2da5
      Nat Goodspeed authored
      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.
      f80b2da5
    • Nat Goodspeed's avatar
      DRTVWR-476: Try to log stderr output from classic-C libraries. · 7845f73c
      Nat Goodspeed authored
      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.
      7845f73c
    • Nat Goodspeed's avatar
      DRTVWR-476: Add LLUniqueFile, adding RAII semantics to LLFILE*. · 9f446be7
      Nat Goodspeed authored
      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.
      9f446be7
    • Nat Goodspeed's avatar
      DRTVWR-476: Use shared_ptr to manage lifespan of coprocedure queue. · cc6f1d61
      Nat Goodspeed authored
      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.
      cc6f1d61
    • Nat Goodspeed's avatar
      DRTVWR-476: Keep coroutine-local data on toplevel()'s stack frame. · 9008124d
      Nat Goodspeed authored
      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.
      9008124d
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      DRTVWR-476: Pump coroutines a few more times when we start quitting. · cbf146f2
      Nat Goodspeed authored
      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.
      cbf146f2
    • Nat Goodspeed's avatar
      DRTVWR-476: Don't name the caught exception · 7541e784
      Nat Goodspeed authored
      unless we're going to reference it.
      7541e784
    • Nat Goodspeed's avatar
      DRTVWR-476: Terminate long-lived coroutines to avoid shutdown crash. · 1345a02b
      Nat Goodspeed authored
      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.
      1345a02b
    • Nat Goodspeed's avatar
      DRTVWR-476: Infrastructure to help manage long-lived coroutines. · 28a54c2f
      Nat Goodspeed authored
      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.
      28a54c2f
    • Nat Goodspeed's avatar
      DRTVWR-476: Mention LLApp::stepFrame() in LLAppViewer::idle() · 253e3600
      Nat Goodspeed authored
      which performs "by hand" the same sequence of calls found in stepFrame().
      
      Why not simply call stepFrame()? Hysterical reasons?
      253e3600
    • Nat Goodspeed's avatar
      DRTVWR-476: Make ~LLEventPumps() call reset() on its way out. · aea1e469
      Nat Goodspeed authored
      ~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.
      aea1e469
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      aaae4478
    • Nat Goodspeed's avatar
      DRTVWR-476: Add LLEventTimer::run_every(), run_at(), run_after(). · 2f866c9d
      Nat Goodspeed authored
      Also add corresponding LLEventTimeout::post_every(), post_at(), post_after()
      methods.
      2f866c9d
    • Nat Goodspeed's avatar
      DRTVWR-476: Eliminate static LLEventPump factory maps. · 95a218fc
      Nat Goodspeed authored
      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.
      95a218fc
    • Nat Goodspeed's avatar
      DRTVWR-476: Seems gcc 4.8 forbids brace-init of reference vars. · 3ec92b0e
      Nat Goodspeed authored
      Although this is legal, apparently there was a bug in the C++11 standard (to
      which gcc 4.8 conforms) that was subsequently fixed in the standard (and thus
      in gcc 4.9). Thanks Henri Beauchamp.
      3ec92b0e
    • Nat Goodspeed's avatar
Loading