DaanDeMeyer / reproc

A cross-platform (C99/C++11) process library
MIT License
552 stars 65 forks source link

reproc combined with catch2 and lldb gives me troubles #8

Closed Alzathar closed 5 years ago

Alzathar commented 5 years ago

reproc version: v2.0.0-beta.4 reproc language: C IDE: Apple LLVM version 9.0.0 (Xcode 9.2) OS: macOS 10.12.6 x64


Catch2

This is not an issue but more a comment about some troubles related to the usage of Catch2 to create unit tests and lldb to manage debug sessions.

Catch2 listen signals (like SIGTERM) and then abort the current test that call REPROC_TERMINATE. This gives Catch2 message like that:

FAILED: {Unknown expression after the reported line} due to a fatal error condition: SIGTERM - Termination request signal

To remove this failure, it is needed to add a signal hander. This code is enough for that:

// Do nothing
void signal_handler(int) {}
// ...
// At the beginning of the unit test
TEST_CASE("...") {
  std::signal(SIGTERM, _test_signal_handler);
}

LLDB

In case you try to debug with LLDB (and maybe GDB) you may have surprise. At least under macOS, the error returned is not what you want. For example, for an invalid command (e.g /I/am/invalid), the returned error is not REPROC_FILE_NOT_FOUND but REPROC_PERMISSION_DENIED. I do not thing there is a workaround for that.

DaanDeMeyer commented 5 years ago

To solve the Catch2 issue, can you try disabling CATCH_CONFIG_POSIX_SIGNALS? I had to enable a similar option to solve similar errors with doctest (which is based on catch).

Is the error under LLDB different from the error returned when using printf or something similar?

Alzathar commented 5 years ago

@DaanDeMeyer Thanks, it works also when I define the symbol CATCH_CONFIG_NO_POSIX_SIGNALS. I also discover that without the definition of this symbol or the proposed custom signal listener, all the unit tests pass if I never run lldb on the binary... I will not dig deeper to understand the reason. The proposed fixes are enough for me.

Regarding LLDB and the returned error, I mean when you run the binary with your unit tests (i.e tests/tests) directly in a terminal, all tests passed as shown below

$ tests/tests
[doctest] doctest version is "2.0.0"
[doctest] run with "--help" for options
===============================================================================
[doctest] test cases:      3 |      3 passed |      0 failed |      0 skipped
[doctest] assertions:     17 |     17 passed |      0 failed |
[doctest] Status: SUCCESS!

However, if I run this binary with LLDB, I have the following results:

$ lldb tests/tests 
(lldb) target create "tests/tests"
Current executable set to 'tests/tests' (x86_64).
(lldb) run
Process 3394 launched: '/Users/alzathar/Downloads/reproc-master/build/tests/tests' (x86_64)
[doctest] doctest version is "2.0.0"
[doctest] run with "--help" for options
===============================================================================
/Users/alzathar/Downloads/reproc-master/tests/stop.cpp:10:
TEST CASE:  stop
  terminate

/Users/alzathar/Downloads/reproc-master/tests/stop.cpp:32: FATAL ERROR: REQUIRE( !error ) is NOT correct!
  values: REQUIRE( false )
  logged: error := 6

===============================================================================
/Users/alzathar/Downloads/reproc-master/tests/working-directory.cpp:6:
TEST CASE:  working-directory

/Users/alzathar/Downloads/reproc-master/tests/working-directory.cpp:22: FATAL ERROR: REQUIRE( !error ) is NOT correct!
  values: REQUIRE( false )
  logged: error := 6

===============================================================================
[doctest] test cases:      3 |      1 passed |      2 failed |      0 skipped
[doctest] assertions:     14 |     12 passed |      2 failed |
[doctest] Status: FAILURE!
Process 3394 exited with status = 1 (0x00000001) 

My guess is LLDB is limited (macOS security feature?) to terminate/kill processes.

DaanDeMeyer commented 5 years ago

I can't reproduce the lldb issue on Linux. It probably has something to do with the way lldb intercepts signals on MacOS causing some system calls to exit with EINTR.

After searching a bit, I think playing a bit with lldb's process signal or process handle might help in solving the issue. I don't have a mac on hand unfortunately so it's hard to debug the issue myself.

Alzathar commented 5 years ago

Thanks for the research. Right now, this LLDB problem is a very low priority for me because all the unit tests pass. In case this problem impacts on my other developments, I will try to find a solution.

For me this issue can be closed because the problem is documented and can be find by other people.