a/src/utils/execmd.cpp b/src/utils/execmd.cpp
...
...
313
private:
313
private:
314
    string        *m_output;
314
    string        *m_output;
315
    ExecCmdAdvise *m_advise;
315
    ExecCmdAdvise *m_advise;
316
};
316
};
317
317
318
319
// The netcon selectloop that doexec() uses for reading/writing would
320
// be complicated to render thread-safe. Use locking to ensure only
321
// one thread in there
322
class ExecLocking {
323
public:
324
    pthread_mutex_t m_mutex;
325
    ExecLocking() 
326
    {
327
  pthread_mutex_init(&m_mutex, 0);
328
    }
329
};
330
ExecLocking o_lock;
331
class ExecLocker {
332
public:
333
    ExecLocker()
334
    {
335
  pthread_mutex_lock(&o_lock.m_mutex);
336
    }
337
    ~ExecLocker()
338
    {
339
  pthread_mutex_unlock(&o_lock.m_mutex);
340
    }
341
};
342
318
int ExecCmd::doexec(const string &cmd, const list<string>& args,
343
int ExecCmd::doexec(const string &cmd, const list<string>& args,
319
            const string *input, string *output)
344
            const string *input, string *output)
320
{
345
{
321
    if (startExec(cmd, args, input != 0, output != 0) < 0) {
346
    if (startExec(cmd, args, input != 0, output != 0) < 0) {
322
    return -1;
347
    return -1;
323
    }
348
    }
324
349
325
    // Cleanup in case we return early
350
    // Cleanup in case we return early
326
    ExecCmdRsrc e(this);
351
    ExecCmdRsrc e(this);
352
    // Only one thread allowed in here...
353
    ExecLocker locker;
327
354
328
    int ret = 0;
355
    int ret = 0;
329
    if (input || output) {
356
    if (input || output) {
330
        // Setup output
357
        // Setup output
331
    if (output) {
358
    if (output) {