Skip to content

Commit

Permalink
refs #4793 do not clear signal mask before execl() after fork() in sy…
Browse files Browse the repository at this point in the history
…stem() to avoid crashes when the child is terminated by a signal
  • Loading branch information
davidnich committed Feb 3, 2024
1 parent 3cd64a0 commit 3ffe130
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 33 deletions.
2 changes: 1 addition & 1 deletion command-line.cpp
@@ -1,4 +1,4 @@
/*
/*
command-line.cpp
Qore Programming Language
Expand Down
67 changes: 35 additions & 32 deletions lib/ql_lib.qpp
Expand Up @@ -91,7 +91,7 @@ extern bool threads_initialized;
AbstractQoreNode* missing_function_error(const char* func, ExceptionSink* xsink) {
QoreString have(func);
have.toupr();
return xsink->raiseException("MISSING-FEATURE-ERROR", "this system does not implement %s(); for maximum portability use the constant Option::HAVE_%s to check if this function is implemented before calling", func, have.getBuffer());
return xsink->raiseException("MISSING-FEATURE-ERROR", "this system does not implement %s(); for maximum portability use the constant Option::HAVE_%s to check if this function is implemented before calling", func, have.c_str());
}

AbstractQoreNode* missing_function_error(const char* func, const char* opt, ExceptionSink* xsink) {
Expand Down Expand Up @@ -285,7 +285,7 @@ exec("/usr/bin/xterm -bg black -fg white -sb -sl 2000");
@endcode
*/
nothing exec(string command) [dom=EXTERNAL_PROCESS,PROCESS] {
ExecArgList exec_args(command->getBuffer());
ExecArgList exec_args(command->c_str());
execvp(exec_args.getFile(), exec_args.getArgs());

xsink->raiseErrnoException("EXEC-ERROR", errno, "execvp() failed in child process for target '%s'", exec_args.getFile());
Expand All @@ -310,31 +310,34 @@ int rc = system("ls -l");
*/
int system(string command) [dom=EXTERNAL_PROCESS] {
#if defined(HAVE_FORK) && defined(HAVE_SIGNAL_HANDLING)
// on platforms with fork(2) and signal handling, we need to fork, enable all signals, then execvp()
pid_t pid;
if (!(pid = fork())) {
// enable all signals
sigset_t mask;
sigemptyset(&mask);
sigprocmask(SIG_SETMASK, &mask, 0);

// exec pgm like system(): sh -c "command"
execl("/bin/sh", "sh", "-c", command->getBuffer(), NULL);
fprintf(stderr, "execvp() failed in child process for target '/bin/sh' with error code %d: %s\n", errno, strerror(errno));
_Exit(-1);
//qore_exit_process(-1);
}
if (pid == -1)
return -1;

// wait for child to exit
int status;
wait(&status);
return WIFEXITED(status) ? WEXITSTATUS(status) : -1;
// on platforms with fork(2) and signal handling, we need to fork, enable all signals, then execl()
pid_t pid;
if (!(pid = fork())) {
// exec pgm like system(): sh -c "command"
execl("/bin/sh", "sh", "-c", command->c_str(), NULL);
fprintf(stderr, "execl() failed in child process for target '/bin/sh' with error code %d: %s\n", errno,
strerror(errno));
_Exit(-1);
//qore_exit_process(-1);
}
if (pid == -1)
return -1;

// wait for child to exit
int status;
//wait(&status);
while (true) {
int rc = waitpid(pid, &status, WUNTRACED);
if (rc == -1 && errno == EINTR) {
continue;
}
break;
}
return WIFEXITED(status) ? WEXITSTATUS(status) : -1;
#elif defined(HAVE_SYSTEM)
return system(command->getBuffer());
return system(command->c_str());
#else
return missing_function_error("system", xsink);
return missing_function_error("system", xsink);
#endif
}

Expand Down Expand Up @@ -807,7 +810,7 @@ string fn = basename("/usr/local/bin/file_name");
@see dirname()
*/
string basename(string path) [flags=CONSTANT] {
char* p = q_basename(path->getBuffer());
char* p = q_basename(path->c_str());
int len = strlen(p);
return new QoreStringNode(p, len, len + 1, path->getEncoding());
}
Expand All @@ -831,7 +834,7 @@ string dir = dirname("/usr/local/bin/file_name");
@see basename()
*/
string dirname(string path) [flags=CONSTANT] {
char* p = q_dirname(path->getBuffer());
char* p = q_dirname(path->c_str());
int len = strlen(p);
return new QoreStringNode(p, len, len + 1, path->getEncoding());
}
Expand Down Expand Up @@ -964,7 +967,7 @@ if (!exists host)
@see gethostbyname_long() for a version of this function that returns all host information, including all hostname aliases and all addresses
*/
*string gethostbyname(string name) [flags=CONSTANT;dom=EXTERNAL_INFO] {
return q_gethostbyname_to_string(name->getBuffer());
return q_gethostbyname_to_string(name->c_str());
}

//! This function variant does nothing at all; it is only included for backwards-compatibility with qore prior to version 0.8.0 for functions that would ignore type errors in arguments
Expand Down Expand Up @@ -993,7 +996,7 @@ if (!exists hostname)
@see gethostbyaddr_long() for a version of this function that returns all host information, including all hostname aliases and all addresses
*/
*string gethostbyaddr(string addr, softint type = AF_INET) [flags=CONSTANT;dom=EXTERNAL_INFO] {
return q_gethostbyaddr_to_string(xsink, addr->getBuffer(), type);
return q_gethostbyaddr_to_string(xsink, addr->c_str(), type);
}

//! This function variant does nothing at all; it is only included for backwards-compatibility with qore prior to version 0.8.0 for functions that would ignore type errors in arguments
Expand All @@ -1018,7 +1021,7 @@ if (!ah)
@see gethostbyname() for a version of this function that returns just the first network address corresponding to the hostname
*/
*hash<auto> gethostbyname_long(string name) [flags=CONSTANT;dom=EXTERNAL_INFO] {
return q_gethostbyname_to_hash(name->getBuffer());
return q_gethostbyname_to_hash(name->c_str());
}

//! This function variant does nothing at all; it is only included for backwards-compatibility with qore prior to version 0.8.0 for functions that would ignore type errors in arguments
Expand Down Expand Up @@ -1047,7 +1050,7 @@ if (!ah)
@see gethostbyaddr() for a simpler version of this function that returns just a single hostname for the address
*/
*hash<auto> gethostbyaddr_long(string addr, softint type = AF_INET) [flags=CONSTANT;dom=EXTERNAL_INFO] {
return q_gethostbyaddr_to_hash(xsink, addr->getBuffer(), type);
return q_gethostbyaddr_to_hash(xsink, addr->c_str(), type);
}

//! This function variant does nothing at all; it is only included for backwards-compatibility with qore prior to version 0.8.0 for functions that would ignore type errors in arguments
Expand All @@ -1074,7 +1077,7 @@ list<hash<auto>> l = getaddrinfo("localhost");
@throw QOREADDRINFO-GETINFO-ERROR nodename nor servname provided, or not known
*/
list<hash<auto>> getaddrinfo(*string node, *softstring service, softint family = AF_UNSPEC, softint flags = 0) [flags=RET_VALUE_ONLY;dom=EXTERNAL_INFO] {
return q_getaddrinfo_to_list(xsink, node ? node->getBuffer() : 0, service ? service->getBuffer() : 0, (int)family, (int)flags);
return q_getaddrinfo_to_list(xsink, node ? node->c_str() : 0, service ? service->c_str() : 0, (int)family, (int)flags);
}

//! closes all possible file descriptors; useful in "daemon" processes that may have inherited open file descriptors
Expand Down

0 comments on commit 3ffe130

Please sign in to comment.