|
a/src/execmd.cpp |
|
b/src/execmd.cpp |
|
... |
|
... |
61 |
|
61 |
|
62 |
extern char **environ;
|
62 |
extern char **environ;
|
63 |
|
63 |
|
64 |
class ExecCmd::Internal {
|
64 |
class ExecCmd::Internal {
|
65 |
public:
|
65 |
public:
|
66 |
Internal()
|
66 |
Internal() {
|
67 |
: m_advise(0), m_provide(0), m_timeoutMs(1000),
|
67 |
sigemptyset(&m_blkcld);
|
68 |
m_rlimit_as_mbytes(0) {
|
|
|
69 |
}
|
68 |
}
|
70 |
|
69 |
|
71 |
static bool o_useVfork;
|
70 |
static bool o_useVfork;
|
72 |
|
71 |
|
73 |
std::vector<std::string> m_env;
|
72 |
vector<string> m_env;
|
74 |
ExecCmdAdvise *m_advise;
|
73 |
ExecCmdAdvise *m_advise{0};
|
75 |
ExecCmdProvide *m_provide;
|
74 |
ExecCmdProvide *m_provide{0};
|
76 |
bool m_killRequest;
|
75 |
bool m_killRequest{false};
|
77 |
int m_timeoutMs;
|
76 |
int m_timeoutMs{1000};
|
78 |
int m_rlimit_as_mbytes;
|
77 |
int m_rlimit_as_mbytes{0};
|
79 |
string m_stderrFile;
|
78 |
string m_stderrFile;
|
80 |
// Pipe for data going to the command
|
79 |
// Pipe for data going to the command
|
81 |
int m_pipein[2];
|
80 |
int m_pipein[2]{-1,-1};
|
82 |
std::shared_ptr<NetconCli> m_tocmd;
|
81 |
std::shared_ptr<NetconCli> m_tocmd;
|
83 |
// Pipe for data coming out
|
82 |
// Pipe for data coming out
|
84 |
int m_pipeout[2];
|
83 |
int m_pipeout[2]{-1,-1};
|
85 |
std::shared_ptr<NetconCli> m_fromcmd;
|
84 |
std::shared_ptr<NetconCli> m_fromcmd;
|
86 |
// Subprocess id
|
85 |
// Subprocess id
|
87 |
pid_t m_pid;
|
86 |
pid_t m_pid{-1};
|
88 |
// Saved sigmask
|
87 |
// Saved sigmask
|
89 |
sigset_t m_blkcld;
|
88 |
sigset_t m_blkcld;
|
90 |
|
89 |
|
91 |
// Reset internal state indicators. Any resources should have been
|
90 |
// Reset internal state indicators. Any resources should have been
|
92 |
// previously freed
|
91 |
// previously freed
|
|
... |
|
... |
98 |
}
|
97 |
}
|
99 |
// Child process code
|
98 |
// Child process code
|
100 |
inline void dochild(const std::string& cmd, const char **argv,
|
99 |
inline void dochild(const std::string& cmd, const char **argv,
|
101 |
const char **envv, bool has_input, bool has_output);
|
100 |
const char **envv, bool has_input, bool has_output);
|
102 |
};
|
101 |
};
|
103 |
bool ExecCmd::Internal::o_useVfork = false;
|
102 |
bool ExecCmd::Internal::o_useVfork{false};
|
104 |
|
103 |
|
105 |
ExecCmd::ExecCmd(int)
|
104 |
ExecCmd::ExecCmd(int)
|
106 |
{
|
105 |
{
|
107 |
m = new Internal();
|
106 |
m = new Internal();
|
108 |
if (m) {
|
107 |
if (m) {
|
|
... |
|
... |
271 |
// this case, we have to conclude that the child process does
|
270 |
// this case, we have to conclude that the child process does
|
272 |
// not exist. Not too sure what causes this, but the previous code
|
271 |
// not exist. Not too sure what causes this, but the previous code
|
273 |
// definitely tried to call killpg(-1,) from time to time.
|
272 |
// definitely tried to call killpg(-1,) from time to time.
|
274 |
pid_t grp;
|
273 |
pid_t grp;
|
275 |
if (m_parent->m_pid > 0 && (grp = getpgid(m_parent->m_pid)) > 0) {
|
274 |
if (m_parent->m_pid > 0 && (grp = getpgid(m_parent->m_pid)) > 0) {
|
276 |
LOGDEB("ExecCmd: killpg(" << (grp) << ", SIGTERM)\n");
|
275 |
LOGDEB("ExecCmd: pid " << m_parent->m_pid << " killpg(" << grp <<
|
|
|
276 |
", SIGTERM)\n");
|
277 |
int ret = killpg(grp, SIGTERM);
|
277 |
int ret = killpg(grp, SIGTERM);
|
278 |
if (ret == 0) {
|
278 |
if (ret == 0) {
|
279 |
for (int i = 0; i < 3; i++) {
|
279 |
for (int i = 0; i < 3; i++) {
|
280 |
msleep(i == 0 ? 5 : (i == 1 ? 100 : 2000));
|
280 |
msleep(i == 0 ? 5 : (i == 1 ? 100 : 2000));
|
281 |
int status;
|
281 |
int status;
|
|
... |
|
... |
331 |
inline void ExecCmd::Internal::dochild(const string& cmd, const char **argv,
|
331 |
inline void ExecCmd::Internal::dochild(const string& cmd, const char **argv,
|
332 |
const char **envv,
|
332 |
const char **envv,
|
333 |
bool has_input, bool has_output)
|
333 |
bool has_input, bool has_output)
|
334 |
{
|
334 |
{
|
335 |
// Start our own process group
|
335 |
// Start our own process group
|
336 |
if (setpgid(0, getpid())) {
|
336 |
if (setpgid(0, 0)) {
|
337 |
LOGINFO("ExecCmd::DOCHILD: setpgid(0, " << getpid() <<
|
337 |
LOGINFO("ExecCmd::DOCHILD: setpgid(0, 0) failed: errno " << errno <<
|
338 |
") failed: errno " << errno << "\n");
|
338 |
"\n");
|
339 |
}
|
339 |
}
|
340 |
|
340 |
|
341 |
// Restore SIGTERM to default. Really, signal handling should be
|
341 |
// Restore SIGTERM to default. Really, signal handling should be
|
342 |
// specified when creating the execmd, there might be other
|
342 |
// specified when creating the execmd, there might be other
|
343 |
// signals to reset. Resetting SIGTERM helps Recoll get rid of its
|
343 |
// signals to reset. Resetting SIGTERM helps Recoll get rid of its
|
|
... |
|
... |
538 |
envv[i++] = 0;
|
538 |
envv[i++] = 0;
|
539 |
|
539 |
|
540 |
// As we are going to use execve, not execvp, do the PATH thing.
|
540 |
// As we are going to use execve, not execvp, do the PATH thing.
|
541 |
string exe;
|
541 |
string exe;
|
542 |
if (!which(cmd, exe)) {
|
542 |
if (!which(cmd, exe)) {
|
543 |
LOGERR("ExecCmd::startExec: " << (cmd) << " not found\n");
|
543 |
LOGERR("ExecCmd::startExec: " << cmd << " not found\n");
|
544 |
free(argv);
|
544 |
free(argv);
|
545 |
free(envv);
|
545 |
free(envv);
|
546 |
return -1;
|
546 |
return 127 << 8;
|
547 |
}
|
547 |
}
|
548 |
//////////////////////////////// End vfork child prepare section.
|
548 |
//////////////////////////////// End vfork child prepare section.
|
549 |
|
549 |
|
550 |
#if HAVE_POSIX_SPAWN && USE_POSIX_SPAWN
|
550 |
#if HAVE_POSIX_SPAWN && USE_POSIX_SPAWN
|
551 |
// Note that posix_spawn provides no way to setrlimit() the child.
|
551 |
// Note that posix_spawn provides no way to setrlimit() the child.
|
|
... |
|
... |
763 |
|
763 |
|
764 |
|
764 |
|
765 |
int ExecCmd::doexec(const string& cmd, const vector<string>& args,
|
765 |
int ExecCmd::doexec(const string& cmd, const vector<string>& args,
|
766 |
const string *input, string *output)
|
766 |
const string *input, string *output)
|
767 |
{
|
767 |
{
|
768 |
|
|
|
769 |
if (startExec(cmd, args, input != 0, output != 0) < 0) {
|
768 |
int status = startExec(cmd, args, input != 0, output != 0);
|
|
|
769 |
if (status) {
|
770 |
return -1;
|
770 |
return status;
|
771 |
}
|
771 |
}
|
772 |
|
772 |
|
773 |
// Cleanup in case we return early
|
773 |
// Cleanup in case we return early
|
774 |
ExecCmdRsrc e(m);
|
774 |
ExecCmdRsrc e(m);
|
775 |
SelectLoop myloop;
|
775 |
SelectLoop myloop;
|