block sigcld, it sometimes causes eintrs during the select() call

This commit is contained in:
dockes 2007-02-19 18:14:13 +00:00
parent 3ee8979ee7
commit 5d1931610f

View File

@ -1,5 +1,5 @@
#ifndef lint #ifndef lint
static char rcsid[] = "@(#$Id: execmd.cpp,v 1.21 2006-12-14 13:53:43 dockes Exp $ (C) 2004 J.F.Dockes"; static char rcsid[] = "@(#$Id: execmd.cpp,v 1.22 2007-02-19 18:14:13 dockes Exp $ (C) 2004 J.F.Dockes";
#endif #endif
/* /*
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -142,17 +142,20 @@ public:
} }
}; };
int ExecCmd::doexec(const string &cmd, const list<string>& args, int ExecCmd::doexec(const string &cmd, const list<string>& args,
const string *inputstring, string *output) const string *inputstring, string *output)
{ {
// Need something to take note of my own errors (apart from the command's)
bool haderror = false;
{ // Debug and logging { // Debug and logging
string command = cmd + " "; string command = cmd + " ";
for (list<string>::const_iterator it = args.begin();it != args.end(); for (list<string>::const_iterator it = args.begin();it != args.end();
it++) { it++) {
command += "{" + *it + "} "; command += "{" + *it + "} ";
} }
LOGDEB(("ExecCmd::doexec: %s\n", command.c_str())); LOGDEB(("ExecCmd::doexec: (%p|%p) %s\n",
inputstring, output, command.c_str()));
} }
const char *input = inputstring ? inputstring->data() : 0; const char *input = inputstring ? inputstring->data() : 0;
unsigned int inputlen = inputstring ? inputstring->length() : 0; unsigned int inputlen = inputstring ? inputstring->length() : 0;
@ -175,9 +178,14 @@ int ExecCmd::doexec(const string &cmd, const list<string>& args,
} }
if (e.pid) { if (e.pid) {
// Ignore SIGPIPE in here. // Ignore SIGPIPE and block SIGCHLD in here.
void (*osig)(int); void (*osig)(int);
osig = signal(SIGPIPE, SIG_IGN); osig = signal(SIGPIPE, SIG_IGN);
sigset_t blkcld;
sigemptyset(&blkcld);
sigaddset(&blkcld, SIGCHLD);
sigprocmask(SIG_BLOCK, &blkcld, 0);
// Father process // Father process
if (input) { if (input) {
close(e.pipein[0]); close(e.pipein[0]);
@ -221,6 +229,7 @@ int ExecCmd::doexec(const string &cmd, const list<string>& args,
} }
LOGERR(("ExecCmd::doexec: select(2) failed. errno %d\n", LOGERR(("ExecCmd::doexec: select(2) failed. errno %d\n",
errno)); errno));
haderror = true;
break; break;
} }
if (e.pipein[1] >= 0 && FD_ISSET(e.pipein[1], &writefds)) { if (e.pipein[1] >= 0 && FD_ISSET(e.pipein[1], &writefds)) {
@ -229,6 +238,7 @@ int ExecCmd::doexec(const string &cmd, const list<string>& args,
if (n < 0) { if (n < 0) {
LOGERR(("ExecCmd::doexec: write(2) failed. errno %d\n", LOGERR(("ExecCmd::doexec: write(2) failed. errno %d\n",
errno)); errno));
haderror = true;
goto out; goto out;
} }
nwritten += n; nwritten += n;
@ -258,6 +268,7 @@ int ExecCmd::doexec(const string &cmd, const list<string>& args,
} else if (n < 0) { } else if (n < 0) {
LOGERR(("ExecCmd::doexec: read(2) failed. errno %d\n", LOGERR(("ExecCmd::doexec: read(2) failed. errno %d\n",
errno)); errno));
haderror = true;
goto out; goto out;
} else if (n > 0) { } else if (n > 0) {
// cerr << "READ: " << n << endl; // cerr << "READ: " << n << endl;
@ -271,13 +282,14 @@ int ExecCmd::doexec(const string &cmd, const list<string>& args,
out: out:
int status = -1; int status = -1;
signal(SIGPIPE, osig);
if (!m_cancelRequest) { if (!m_cancelRequest) {
(void)waitpid(e.pid, &status, 0); (void)waitpid(e.pid, &status, 0);
e.pid = -1; e.pid = -1;
} }
signal(SIGPIPE, osig);
sigprocmask(SIG_UNBLOCK, &blkcld, 0);
LOGDEB1(("ExecCmd::doexec: father got status 0x%x\n", status)); LOGDEB1(("ExecCmd::doexec: father got status 0x%x\n", status));
return status; return haderror ? -1 : status;
} else { } else {
// In child process. Set up pipes, environment, and exec command // In child process. Set up pipes, environment, and exec command