#include <fcntl.h>
#include <pty.h> // openpty
#include <stdlib.h> // setenv
+#include <sys/prctl.h> // prctl(), PR_SET_PDEATHSIG
#include <cstring> // strsignal
#include <iostream>
- void ExternalProgram::start_program( const char *const *argv,
+ void ExternalProgram::start_program(const char *const *argv,
const Environment & environment,
Stderr_Disposition stderr_disp,
int stderr_fd,
bool default_locale,
- const char * root )
+ const char * root , bool switch_pgid, bool die_with_parent )
{
pid = -1;
_exitStatus = 0;
cmdstr << " > '" << redirectStdout << "'";
_command = cmdstr.str();
}
- DBG << "Executing " << _command << endl;
+ DBG << "Executing" << (default_locale?"[C] ":" ") << _command << endl;
if (use_pty)
}
}
+ pid_t ppid_before_fork = ::getpid();
+
// Create module process
if ((pid = fork()) == 0)
{
}
else
{
+ if ( switch_pgid )
+ setpgid( 0, 0);
renumber_fd (to_external[0], 0); // set new stdin
::close(from_external[0]); // Belongs to father process
::close( i );
}
+ if ( die_with_parent ) {
+ // process dies with us
+ int r = prctl(PR_SET_PDEATHSIG, SIGTERM);
+ if (r == -1) {
+ //ignore if it did not work, worst case the process lives on after the parent dies
+ std::cerr << "Failed to set PR_SET_PDEATHSIG" << endl;// After fork log on stderr too
+ }
+
+ // test in case the original parent exited just
+ // before the prctl() call
+ pid_t ppidNow = getppid();
+ if (ppidNow != ppid_before_fork) {
+ std::cerr << "PPID changed from "<<ppid_before_fork<<" to "<< ppidNow << endl;// After fork log on stderr too
+ _exit(128);
+ }
+ }
+
execvp(argv[0], const_cast<char *const *>(argv));
// don't want to get here
_execError = str::form( _("Can't exec '%s' (%s)."), argv[0], strerror(errno) );
} while ( true );
}
- // Wait for child to exit
- int ret;
- int status = 0;
- do
+ if ( pid > 0 ) // bsc#1109877: must re-check! running() in the loop above may have already waited.
{
- ret = waitpid(pid, &status, 0);
- }
- while (ret == -1 && errno == EINTR);
+ // Wait for child to exit
+ int ret;
+ int status = 0;
+ do
+ {
+ ret = waitpid(pid, &status, 0);
+ }
+ while (ret == -1 && errno == EINTR);
- if (ret != -1)
- {
- _exitStatus = checkStatus( status );
+ if (ret != -1)
+ {
+ _exitStatus = checkStatus( status );
+ }
+ pid = -1;
}
- pid = -1;
}
return _exitStatus;
return true;
}
+ bool ExternalProgram::kill(int sig)
+ {
+ if (pid > 0)
+ {
+ ::kill(pid, sig);
+ }
+ return true;
+ }
bool
ExternalProgram::running()