Switch to unified view

a/src/utils/execmd.cpp b/src/utils/execmd.cpp
...
...
183
// In child process. Set up pipes and exec command. 
183
// In child process. Set up pipes and exec command. 
184
// This must not return. _exit() on error.
184
// This must not return. _exit() on error.
185
// *** This can be called after a vfork, so no modification of the
185
// *** This can be called after a vfork, so no modification of the
186
//     process memory at all is allowed ***
186
//     process memory at all is allowed ***
187
// The LOGXX calls should not be there, but they occur only after "impossible"
187
// The LOGXX calls should not be there, but they occur only after "impossible"
188
// errors, which we would most definitely want to have a hint about
188
// errors, which we would most definitely want to have a hint about.
189
//
190
// Note that any of the LOGXX calls could block on a mutex set in the
191
// father process, so that only absolutely exceptional conditions, 
192
// should be logged, for debugging and post-mortem purposes
193
// If one of the calls block, the problem manifests itself by 20mn
194
// (filter timeout) of looping on "ExecCmd::doexec: selectloop
195
// returned 1', because the father is waiting on the read descriptor
189
inline void ExecCmd::dochild(const string &cmd, const char **argv,
196
inline void ExecCmd::dochild(const string &cmd, const char **argv,
190
                 const char **envv,
197
                 const char **envv,
191
                 bool has_input, bool has_output)
198
                 bool has_input, bool has_output)
192
{
199
{
193
    // Start our own process group
200
    // Start our own process group
194
    if (setpgid(0, getpid())) {
201
    if (setpgid(0, getpid())) {
195
    LOGINFO(("ExecCmd::dochild: setpgid(0, %d) failed: errno %d\n",
202
    LOGINFO(("ExecCmd::DOCHILD: setpgid(0, %d) failed: errno %d\n",
196
         getpid(), errno));
203
         getpid(), errno));
197
    }
204
    }
198
205
199
    // Restore SIGTERM to default. Really, signal handling should be
206
    // Restore SIGTERM to default. Really, signal handling should be
200
    // specified when creating the execmd. Help Recoll get rid of its
207
    // specified when creating the execmd. Help Recoll get rid of its
201
    // filter children though. To be fixed one day... Not sure that
208
    // filter children though. To be fixed one day... Not sure that
202
    // all of this is needed. But an ignored sigterm and the masks are
209
    // all of this is needed. But an ignored sigterm and the masks are
203
    // normally inherited.
210
    // normally inherited.
204
    if (signal(SIGTERM, SIG_DFL) == SIG_ERR) {
211
    if (signal(SIGTERM, SIG_DFL) == SIG_ERR) {
205
    LOGERR(("ExecCmd::dochild: signal() failed, errno %d\n", errno));
212
    //LOGERR(("ExecCmd::DOCHILD: signal() failed, errno %d\n", errno));
206
    }
213
    }
207
    sigset_t sset;
214
    sigset_t sset;
208
    sigfillset(&sset);
215
    sigfillset(&sset);
209
    pthread_sigmask(SIG_UNBLOCK, &sset, 0);
216
    pthread_sigmask(SIG_UNBLOCK, &sset, 0);
210
    sigprocmask(SIG_UNBLOCK, &sset, 0);
217
    sigprocmask(SIG_UNBLOCK, &sset, 0);
...
...
218
    }
225
    }
219
    if (has_output) {
226
    if (has_output) {
220
    close(m_pipeout[0]);
227
    close(m_pipeout[0]);
221
    if (m_pipeout[1] != 1) {
228
    if (m_pipeout[1] != 1) {
222
        if (dup2(m_pipeout[1], 1) < 0) {
229
        if (dup2(m_pipeout[1], 1) < 0) {
223
        LOGERR(("ExecCmd::doexec: dup2(2) failed. errno %d\n", errno));
230
        LOGERR(("ExecCmd::DOCHILD: dup2() failed. errno %d\n", errno));
224
        }
231
        }
225
        if (close(m_pipeout[1]) < 0) {
232
        if (close(m_pipeout[1]) < 0) {
226
        LOGERR(("ExecCmd::doexec: close(2) failed. errno %d\n", errno));
233
        LOGERR(("ExecCmd::DOCHILD: close() failed. errno %d\n", errno));
227
        }
234
        }
228
    }
235
    }
229
    }
236
    }
230
    // Do we need to redirect stderr ?
237
    // Do we need to redirect stderr ?
231
    if (!m_stderrFile.empty()) {
238
    if (!m_stderrFile.empty()) {
...
...
246
253
247
    // Close all descriptors except 0,1,2
254
    // Close all descriptors except 0,1,2
248
    libclf_closefrom(3);
255
    libclf_closefrom(3);
249
256
250
    execve(cmd.c_str(), (char *const*)argv, (char *const*)envv);
257
    execve(cmd.c_str(), (char *const*)argv, (char *const*)envv);
251
    // Hu ho
258
    // Hu ho. This should never happened as we checked the existence of the
259
    // executable before calling dochild... Until we did this, this was 
260
    // the chief cause of LOG mutex deadlock
252
    LOGERR(("ExecCmd::doexec: execve(%s) failed. errno %d\n", cmd.c_str(),
261
    LOGERR(("ExecCmd::DOCHILD: execve(%s) failed. errno %d\n", cmd.c_str(),
253
        errno));
262
        errno));
254
    _exit(127);
263
    _exit(127);
255
}
264
}
256
265
257
int ExecCmd::startExec(const string &cmd, const vector<string>& args,
266
int ExecCmd::startExec(const string &cmd, const vector<string>& args,
...
...
290
    typedef const char *Ccharp;
299
    typedef const char *Ccharp;
291
    Ccharp *argv;
300
    Ccharp *argv;
292
    argv = (Ccharp *)malloc((args.size()+2) * sizeof(char *));
301
    argv = (Ccharp *)malloc((args.size()+2) * sizeof(char *));
293
    if (argv == 0) {
302
    if (argv == 0) {
294
    LOGERR(("ExecCmd::doexec: malloc() failed. errno %d\n", errno));
303
    LOGERR(("ExecCmd::doexec: malloc() failed. errno %d\n", errno));
295
  exit(1);
304
        return -1;
296
    }
305
    }
297
    // Fill up argv
306
    // Fill up argv
298
    argv[0] = cmd.c_str();
307
    argv[0] = cmd.c_str();
299
    int i = 1;
308
    int i = 1;
300
    vector<string>::const_iterator it;
309
    vector<string>::const_iterator it;
...
...
307
    int envsize;
316
    int envsize;
308
    for (envsize = 0; ; envsize++) 
317
    for (envsize = 0; ; envsize++) 
309
    if (environ[envsize] == 0)
318
    if (environ[envsize] == 0)
310
        break;
319
        break;
311
    envv = (Ccharp *)malloc((envsize + m_env.size() + 2) * sizeof(char *));
320
    envv = (Ccharp *)malloc((envsize + m_env.size() + 2) * sizeof(char *));
321
    if (envv == 0) {
322
  LOGERR(("ExecCmd::doexec: malloc() failed. errno %d\n", errno));
323
        free(argv);
324
        return -1;
325
    }
312
    int eidx;
326
    int eidx;
313
    for (eidx = 0; eidx < envsize; eidx++)
327
    for (eidx = 0; eidx < envsize; eidx++)
314
    envv[eidx] = environ[eidx];
328
    envv[eidx] = environ[eidx];
315
    for (vector<string>::const_iterator it = m_env.begin(); 
329
    for (vector<string>::const_iterator it = m_env.begin(); 
316
     it != m_env.end(); it++) {
330
     it != m_env.end(); it++) {
317
    envv[eidx++] = it->c_str();
331
    envv[eidx++] = it->c_str();
318
    }
332
    }
319
    envv[eidx] = 0;
333
    envv[eidx] = 0;
320
334
321
    // As we are going to use execve, not execvp, do the PATH
335
    // As we are going to use execve, not execvp, do the PATH thing.
322
    // thing. If the command is not found, exe will be empty and the
323
    // exec will fail, which is what we want.
324
    string exe;
336
    string exe;
325
    which(cmd, exe);
337
    if (!which(cmd, exe)) {
338
        LOGERR(("ExecCmd::startExec: %s not found\n", cmd.c_str()));
339
        free(argv);
340
        free(envv);
341
        return -1;
342
    }
326
////////////////////////////////
343
////////////////////////////////
327
344
328
    if (o_useVfork) {
345
    if (o_useVfork) {
329
    m_pid = vfork();
346
    m_pid = vfork();
330
    } else {
347
    } else {
...
...
342
    // dochild does not return. Just in case...
359
    // dochild does not return. Just in case...
343
    _exit(1);
360
    _exit(1);
344
    }
361
    }
345
362
346
    // Father process
363
    // Father process
364
347
////////////////////
365
////////////////////
348
    // Vfork cleanup section
366
    // Vfork cleanup section
349
    free(argv);
367
    free(argv);
350
    free(envv);
368
    free(envv);
351
///////////////////
369
///////////////////
...
...
353
    // Set the process group for the child. This is also done in the
371
    // Set the process group for the child. This is also done in the
354
    // child process see wikipedia(Process_group)
372
    // child process see wikipedia(Process_group)
355
    if (setpgid(m_pid, m_pid)) {
373
    if (setpgid(m_pid, m_pid)) {
356
        // This can fail with EACCES if the son has already done execve 
374
        // This can fail with EACCES if the son has already done execve 
357
        // (linux at least)
375
        // (linux at least)
358
        LOGDEB(("ExecCmd: father setpgid(son)(%d,%d) errno %d (ok)\n",
376
        LOGDEB2(("ExecCmd: father setpgid(son)(%d,%d) errno %d (ok)\n",
359
                m_pid, m_pid, errno));
377
                 m_pid, m_pid, errno));
360
    }
378
    }
361
379
362
    sigemptyset(&m_blkcld);
380
    sigemptyset(&m_blkcld);
363
    sigaddset(&m_blkcld, SIGCHLD);
381
    sigaddset(&m_blkcld, SIGCHLD);
364
    pthread_sigmask(SIG_BLOCK, &m_blkcld, 0);
382
    pthread_sigmask(SIG_BLOCK, &m_blkcld, 0);