Skip to content
Snippets Groups Projects
  1. Feb 24, 2012
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      Add LLStringUtil::getTokens() overload handling quoted substrings. · 025329b6
      Nat Goodspeed authored
      We didn't have any tokenizer suitable for scanning something like a bash
      command line. We do have a couple hacks, e.g. LLExternalEditor::tokenize() and
      LLCommandLineParser::parseCommandLineString(). Both try to work around
      boost::tokenizer limitations; but existing boost::tokenizer support just
      doesn't address this case. Neither of the above is available as a general
      scanner anyway, and parseCommandLineString() fails outright when passed "".
      New getTokens() also distinguishes between "drop delimiters" (e.g. space,
      return, newline) to be discarded from the token stream, versus "keep
      delimiters" (e.g. "+-*/") to be returned as tokens in their own right.
      There's an overload that honors escapes and a more efficient one that doesn't;
      each has a convenience overload that returns the scanned string vector rather
      than requiring a separate declaration.
      Tweak and comment older getTokens() implementation.
      Add unit tests for both old and new getTokens() implementations.
      Break out StringVec and std::ostream << StringVec from
      indra/llcommon/tests/listener.h to StringVec.h: that's coming in handy for a
      number of different TUT test sources.
      025329b6
  2. Feb 23, 2012
    • Nat Goodspeed's avatar
      Tighten up LLProcess pipe support, per Richard's code review. · 14ddc647
      Nat Goodspeed authored
      Clarify wording in some of the doc comments; be a bit more explicit about some
      of the parameter fields.
      Make some query methods 'const'.
      Change default LLProcess::ReadPipe::getLimit() value to 0: don't post any
      incoming data with notification event unless caller requests it. But do post
      pertinent FILESLOT in case caller reuses same listener for both stdout and
      stderr.
      Use more idiomatic, readable syntax for accessing LLProcess::Params data.
      14ddc647
  3. Feb 20, 2012
    • Nat Goodspeed's avatar
      Let LLProcess consumer specify desired description for logging. · 999484a6
      Nat Goodspeed authored
      If caller runs (e.g.) a Python script, it's not very helpful to a human log
      reader to keep seeing LLProcess instances logged as /pathname/to/python (pid).
      If caller is aware, the code can at least use the script name as the desc --
      or maybe even a hint as to the script's purpose.
      If caller doesn't explicitly pass a desc, at least shorten to just the
      basename of the executable.
      999484a6
    • Nat Goodspeed's avatar
      Make LLProcess post termination event to specified pump if desired. · 8b5d5f96
      Nat Goodspeed authored
      This way a caller need not spin on isRunning(); we can just listen for the
      requested termination event.
      Post a similar event containing error message if for any reason
      LLProcess::create() failed to launch the child.
      Add unit tests for both cases.
      8b5d5f96
  4. Feb 18, 2012
  5. Feb 16, 2012
    • Nat Goodspeed's avatar
      Fix typos in a few LLProcess::ReadPipe::find() unit tests. · f52cf4be
      Nat Goodspeed authored
      The typos didn't make for invalid tests, but they made a few tests redundant
      while leaving other (subtly different) cases untested.
      f52cf4be
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      Fix bug in LLProcess::ReadPipe::peek() substring computation. · a06ba836
      Nat Goodspeed authored
      Add unit tests for peek() with substring args, reimplemented contains(),
      various forms of find().
      (yay unit tests)
      a06ba836
    • Nat Goodspeed's avatar
      4ecf9d6a
    • Nat Goodspeed's avatar
      Add LLProcess::ReadPipe::find() methods, with corresponding npos. · e92c3113
      Nat Goodspeed authored
      If it's useful to have contains() to tell you whether incoming data contains a
      particular substring, and if it's useful for contains() and peek() to accept
      an offset within that data, then it's useful to allow you to get the offset of
      a desired substring within that data. But of course a find() returning offset
      needs something like std::string::npos for "not found"; borrow that
      convention.
      Support both find(const std::string&) and find(char); the latter permits a
      more efficient implementation. In fact, make find(string) recognize a string
      of length 1 and leverage the find(char) implementation.
      Given that, reimplement contains(mumble) as shorthand for find(mumble) != npos.
      Implement find() overloads using std::search() and std::find() on
      boost::asio::streambuf character iterators, rather than copying to std::string
      and then using string search like previous contains() implementation.
      Reimplement WritePipeImpl::tick() and ReadPipeImpl::tick() to write/read
      directly from/to boost::asio::streambuf data, instead of copying to/from a
      temporary flat buffer.
      As long as ReadPipeImpl::tick() keeps successfully filling buffers, keep
      reading. Previous implementation would only handle a long child write over
      successive tick() calls. Stop on read error or when we come up short.
      e92c3113
  6. Feb 15, 2012
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      Don't be confused by "\r\n" line endings on pipe on Windows. · fc6d70db
      Nat Goodspeed authored
      These are all very well when we just want to dump the output to a log, or
      whatever, but in a unit-test context it matters for comparison.
      fc6d70db
    • Nat Goodspeed's avatar
      Add LLProcess::ReadPipe::size(), peek(), contains(). · 56d93121
      Nat Goodspeed authored
      Also add "len" key to event data on LLProcess::getPump(). If you've used
      setLimit(), event["data"].length() may not reflect the length of the
      accumulated data in the ReadPipe.
      Add unit test with stdin/stdout handshake with child process.
      56d93121
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      Fix llprocess_test.cpp's exception catching for Linux. · 10ab4adc
      Nat Goodspeed authored
      In the course of re-enabling the indra/test tests last year, Log generalized a
      workaround I'd introduced in llsdmessage_test.cpp. In Linux viewer land, a
      test program trying to catch an expected exception can't seem to catch it by
      its specific class (across the libllcommon.so boundary), but must instead
      catch std::runtime_error and validate the typeid().name() string. Log added a
      macro for this idiom in llevents_tut.cpp. Generalize that macro further for
      normal-case processing as well, move it to a header file of its own and use it
      in all known places -- plus the new exception-catching tests in
      llprocess_test.cpp.
      10ab4adc
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      Preliminary pipe support for LLProcess. · e239cad1
      Nat Goodspeed authored
      Add LLProcess::FileParam to specify how to construct each child's standard
      file slot, with lots of comments about features designed but not yet
      implemented. The point is to design it with enough flexibility to be able to
      extend to foreseeable use cases.
      Add LLProcess::Params::files to collect up to 3 FileParam items. Naturally
      this extends the accepted LLSD syntax as well.
      Implement type="" (child inherits parent file descriptor) and "pipe" (parent
      constructs anonymous pipe to pass to child).
      Add LLProcess::FILESLOT enum, plus methods:
      getReadPipe(FILESLOT), getOptReadPipe(FILESLOT)
      getWritePipe(), getOptWritePipe()
      getPipeName(FILESLOT): placeholder implementation for now
      Add LLProcess::ReadPipe and WritePipe classes, as returned by get*Pipe().
      WritePipe supports get_ostream() method for streaming to child stdin.
      ReadPipe supports get_istream() method for reading from child stdout/stderr.
      It also provides getPump() returning LLEventPump& so interested parties can
      listen for arrival of new data on the aforementioned std::istream.
      For "pipe" slots, instantiate appropriate *Pipe class.
      ReadPipe and WritePipe classes are pure virtual bases for ReadPipeImpl and
      WritePipeImpl, respectively: all implementation data are hidden in the latter
      classes, visible only in llprocess.cpp. In fact each *PipeImpl class registers
      itself for "mainloop" ticks, attempting nonblocking I/O to the underlying
      apr_file_t on each tick. Data are buffered in a boost::asio::streambuf, which
      bridges between std::[io]stream and the APR I/O calls.
      Sanity-test ReadPipeImpl by using a pipe to absorb the Python "SyntaxError"
      output from the successful syntax_error test, rather than alarming the user.
      Add first few unit tests for validating FileParam. More tests coming!
      e239cad1
  7. Feb 13, 2012
    • Nat Goodspeed's avatar
      Use per-frame ticks on "mainloop" LLEventPump to update LLProcess. · aae61392
      Nat Goodspeed authored
      When we reimplemented LLProcess on APR, necessitating APR's funny callback
      mechanism to sense child-process status, every isRunning() or getStatus() call
      called the APR poll function that calls ALL registered LLProcess callbacks. In
      other words, every time any consumer called any LLProcess::isRunning() method,
      all LLProcess callbacks were redundantly fired. Change that so that the single
      APR poll function is called once per frame, courtesy of the "mainloop"
      LLEventPump. Once per viewer frame should be well within the realtime duration
      in which it's reasonable to expect child-process status to change.
      In effect, this changes LLProcess's public API to introduce a dependency on
      "mainloop" ticks. Add such ticks to llprocess_test.cpp as well.
      aae61392
    • Nat Goodspeed's avatar
      d4f887e4
    • Nat Goodspeed's avatar
  8. Feb 12, 2012
  9. Feb 11, 2012
  10. Feb 10, 2012
    • Nat Goodspeed's avatar
      Eliminate ManifestError for wildcards matching 0 files. · acd46062
      Nat Goodspeed authored
      Turns out that some (many?) wildcard LLManifest.path(wildcard) calls are "just
      in case": sweep up any (e.g.) "*.tga" files there may be, but no problem if
      there are none.
      Change path() logic so it tries the next tree (source, artwork, build) if
      either a specific (non-wildcard) filename doesn't exist, as now, OR if a
      wildcard matches 0 files in the current tree. This continues to support "just
      in case" wildcards, while permitting wildcards to work in the artwork and
      build trees as well as the source tree.
      Use a more specific exception than ManifestError for missing file. Only in
      that case should we try the next tree. Any other ManifestError should
      propagate.
      acd46062
    • Nat Goodspeed's avatar
      Try using Log's new APR packages for Windows, Mac, Linux. · 9011b044
      Nat Goodspeed authored
      This APR merges work from Huseby, Log, Leslie, Nat.
      9011b044
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      Use wildcards instead of many version-specific lib names on Linux. · 028a05e7
      Nat Goodspeed authored
      viewer_manifest.py's Linux_i686Manifest class has contained directives to copy
      library files with names like (e.g.) "libapr-1.so.0.4.2", which means that
      every update to any such library requires messing with viewer_manifest.py.
      But LLManifest.path() claims to support wildcards, and it's more robust to
      specify "libapr-1.so*" instead.
      Unfortunately LLManifest.path()'s wildcard support only used to work for files
      in the source tree (vs. the artwork tree or the build tree). The logic in
      path() tries each tree in turn, relying on an exception to make it try the
      next tree. This exception was raised for a nonexistent specific filename --
      but it never used to raise that exception for a wildcard matching 0 files.
      Instead it would simply report "0 files" and proceed, producing an invalid
      viewer install.
      Raise that exception for a wildcard matching nothing. This forces path() to
      consider the artwork tree and the build tree, permitting us to use wildcards
      in library names.
      Define an exception specific to LLManifest: ManifestException rather than the
      generic Python RuntimeException. Make it a subclass of RuntimeException so any
      existing callers expecting to catch RuntimeException will continue to work.
      028a05e7
  11. Feb 09, 2012
  12. Feb 07, 2012
  13. Feb 06, 2012
Loading