1

I'm using the Apache Portable Runtime to start a process via apr_procattr_create. My failing test case is when the called command does not exist on the system. On Windows, apr_proc_create returns a non-success error code if the executable does not exist. On Linux, I cannot work out how to detect the failure. According to the documentation, apr_procattr_error_check_set might be expected to do the trick, but it does not appear to.

Q: How can I detect that a process failed to start on linux with APR apr_proc_create?

Here's my code:

/**
 * Run a command asynchronously
 * The command name is the first element of args. The remaining elements are
 * the arguments for the command 
 */
apr_status_t mynamespace::RunCommandUnchecked(const std::vector<std::string> & args)
{
    std::vector<const char*> cArgs;
    for (size_t i = 0; i < args.size(); ++i)
        cArgs.push_back(args[i].c_str());
    cArgs.push_back(nullptr);

    apr_procattr_t *procAttr;
    apr_procattr_create(&procAttr, this->impl->pool.get_Pool());

    // send the process's std out to a temporary file
    apr_procattr_child_out_set(procAttr, this->impl->outputFile, nullptr);

    // block the process from accessing stdin & stderr on the current process
    apr_procattr_child_in_set(procAttr, nullptr, nullptr);
    apr_procattr_child_err_set(procAttr, nullptr, nullptr);

    // prefer to report errors to the caller.
    apr_procattr_error_check_set(procAttr, 1);

    // Ensure the path is searched for the command to run
    apr_procattr_cmdtype_set(procAttr, APR_PROGRAM_PATH);

    return apr_proc_create(&this->impl->proc, cArgs[0], cArgs.data(), nullptr, procAttr, this->impl->pool.get_Pool());
}

My (failing on linux) test case is as follows:

/*
 *
 * In this test, we execute a command that does not exist. We expect
 * a non-success failure code.
 **/
void CommandRunnerTests::CommandDoesNotExistUnchecked()
{
    mynamespace::CommandRunner runner(app::get_ApplicationLog());
    auto rv = runner.RunCommandUnchecked({ "pants-trousers-stockings.exe" });

    // We expect a non-success error code to be returned.
    // This assert fails on linux.
    CPPUNIT_ASSERT(rv != APR_SUCCESS);

#ifdef _WIN32
    std::string expected("The system cannot find the file specified.");
#else
    std::string expected("command not found");
#endif

    auto msg = app::GetAprErrorMessage(rv);
    CPPUNIT_ASSERT_STRING_EQUAL(expected, boost::trim_copy(msg)); 
}

When I execute the same command on the (bash) shell, the output is as follows

me@pc:~/code$ pants-trousers-stockings.exe
pants-trousers-stockings.exe: command not found
me@pc:~/code$ echo $?
127
  • I'm currently using APR version 1.4.6. I can update to a newer version if there are any relevant changes, but I don't see any in the release notes.
  • The code works as expected on Windows.
  • My Linux OS is uBuntu 14.04
  • Calling apr_proc_wait doesn't work to detect the failure, it just tells me APR_PROC_EXIT (process terminated normally) and APR_CHILD_DONE (child is no longer running).
Boinst
  • 3,365
  • 2
  • 38
  • 60

0 Answers0