Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is C++'s system() synchronized?

I'm writing a small utility which is supposed to launch several commands in parallel using system() and wait for their results for logging purposes. However, even though I'm calling system() on different threads, by looking at my Activity Monitor I only see one instance of each command at a time. It looks like system is internally synchronized on a mutex, and only one execution is allowed at each time, however this looks like a huge limitation, can someone confirm this behavior? Do you have any ideas on how to solve it?

Update by looking at the threads execution flow, it looks like they're effectively synchronizing on a mutex. Is there an alternative system() which doesn't do that?

threads

I should mention I'm using C++11 (w/ clang and libc++) on Mac OS 10.7.5.

Update code is:

void Batch::run()
{
    done.clear();
    generator->resetGeneration();

    while(generator->hasMoreParameters())
    {
        // Lock for accessing active
        unique_lock<mutex> lock(q_mutex, adopt_lock);

        // If we've less experiments than threads
        if (active.size() < threads)
        {
            Configuration conf = generator->generateParameters();
            Experiment e(executable, conf);

            thread t(&Experiment::run, e, reference_wrapper<Batch>(*this));
            thread::id id = t.get_id();
            active.insert(id);
            t.detach();
        }

        // Condition variable
        q_control.wait(lock, [this] { return active.size() < threads; } );

    }
}

void Batch::experimentFinished(std::thread::id pos)
{
    unique_lock<mutex> lock(q_mutex, adopt_lock);
    active.erase(pos);
    lock.unlock();
    q_control.notify_all();
}

void Experiment::run(Batch& caller)
{    
    // Generate run command
    stringstream run_command;
    run_command << executable + " ";
    ParameterExpression::printCommandLine(run_command, config);

    if (system(run_command.str().c_str()))
        stats["success"] = "true";
    else
        stats["success"] = "false";

    caller.experimentFinished(this_thread::get_id());
}

Just to be clear: the spawning and handling of threads works fine and does what it needs to do, but it looks like you can have just one instance of system() running at a time.

Thanks

like image 883
tunnuz Avatar asked Sep 01 '25 04:09

tunnuz


1 Answers

POSIX has this to say about system(3):

Using the system() function in more than one thread in a process or when the SIGCHLD signal is being manipulated by more than one thread in a process may produce unexpected results.

Due to the way that SIGCHLD must be blocked during the execution, running system calls concurrently doesn't really work. If you want multiple threads to run external tasks, you'll need to write a bit more code (handling fork/exec/wait yourself).

like image 84
Mat Avatar answered Sep 02 '25 16:09

Mat