Skip to content

Commit

Permalink
Merge pull request #5486 from BOINC/dpa_sigstop
Browse files Browse the repository at this point in the history
Wrapper (Unix): use SIGSTOP instead of SIGTSTP to suspend subprocesses
  • Loading branch information
AenBleidd authored Jan 9, 2024
2 parents 95adf93 + 86f6f17 commit 60c6d6b
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 12 deletions.
28 changes: 19 additions & 9 deletions lib/proc_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,35 +245,45 @@ void kill_descendants(int child_pid) {
}
#endif

// suspend/resume the descendants of the calling process
// (or if pid==0, the calling process)
// suspend/resume the descendants of the calling process.
// Unix version lets you choose the stop signal:
// SIGSTOP (the default) can't be caught.
// SIGTSTP can be caught, but it has no effect for processes without a TTY.
// So it's useful only for programs that are wrappers of some sort;
// they must catch and handle it.
//
#ifdef _WIN32
void suspend_or_resume_descendants(bool resume) {
vector<int> descendants;
#ifdef _WIN32
int pid = GetCurrentProcessId();
get_descendants(pid, descendants);
suspend_or_resume_threads(descendants, 0, resume, false);
}
#else
void suspend_or_resume_descendants(bool resume, bool use_tstp) {
vector<int> descendants;
int pid = getpid();
get_descendants(pid, descendants);
for (unsigned int i=0; i<descendants.size(); i++) {
kill(descendants[i], resume?SIGCONT:SIGTSTP);
kill(descendants[i], resume?SIGCONT:(use_tstp?SIGTSTP:SIGSTOP));
}
#endif
}
#endif

// used by the wrapper
// Suspend/resume the given process; used by the wrapper.
// See signal comment above.
//
void suspend_or_resume_process(int pid, bool resume) {
#ifdef _WIN32
void suspend_or_resume_process(int pid, bool resume) {
vector<int> pids;
pids.push_back(pid);
suspend_or_resume_threads(pids, 0, resume, false);
}
#else
::kill(pid, resume?SIGCONT:SIGTSTP);
#endif
void suspend_or_resume_process(int pid, bool resume, bool use_tstp) {
::kill(pid, resume?SIGCONT:(use_tstp?SIGTSTP:SIGSTOP));
}
#endif

// return OS-specific value associated with priority code
//
Expand Down
6 changes: 4 additions & 2 deletions lib/proc_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ extern void kill_descendants();
extern int suspend_or_resume_threads(
std::vector<int> pids, DWORD threadid, bool resume, bool check_exempt
);
extern void suspend_or_resume_descendants(bool resume);
extern void suspend_or_resume_process(int pid, bool resume);
#else
extern void kill_descendants(int child_pid=0);
extern void suspend_or_resume_descendants(bool resume, bool use_tstp=false);
extern void suspend_or_resume_process(int pid, bool resume, bool use_tstp=false);
#endif
extern void suspend_or_resume_descendants(bool resume);
extern void suspend_or_resume_process(int pid, bool resume);

extern int process_priority_value(int);

Expand Down
21 changes: 20 additions & 1 deletion samples/wrapper/wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
// --trickle X send a trickle-up message reporting runtime every X sec
// of runtime (use this for credit granting
// if your app does its own job management)
// --use_tstp use SIGTSTP instead of SIGSTOP to suspend children
// (Unix only). SIGTSTP can be caught.
// Use this if the wrapped program is itself a wrapper.
//
// Handles:
// - suspend/resume/quit/abort
Expand Down Expand Up @@ -89,6 +92,8 @@
using std::vector;
using std::string;

bool use_tstp = false;

#ifdef DEBUG
inline void debug_msg(const char* x) {
fprintf(stderr, "[DEBUG] %s\n", x);
Expand Down Expand Up @@ -996,7 +1001,7 @@ void TASK::kill() {
kill_descendants(pid);
#endif
}

#ifdef _WIN32
void TASK::stop() {
if (multi_process) {
suspend_or_resume_descendants(false);
Expand All @@ -1005,6 +1010,17 @@ void TASK::stop() {
}
suspended = true;
}
#else
void TASK::stop() {
if (multi_process) {
suspend_or_resume_descendants(false, use_tstp);
}
else {
suspend_or_resume_process(pid, false, use_tstp);
}
suspended = true;
}
#endif

void TASK::resume() {
if (multi_process) {
Expand Down Expand Up @@ -1168,6 +1184,7 @@ void usage() {
" --sporadic\n"
" --trickle X\n"
" --version\n"
" --use_tstp\n"
);
boinc_finish(EXIT_INIT_FAILURE);
}
Expand Down Expand Up @@ -1207,6 +1224,8 @@ int main(int argc, char** argv) {
fprintf(stderr, "%s\n", SVN_VERSION);
boinc_finish(0);
#endif
} else if (!strcmp(argv[j], "--use_tstp")) {
use_tstp = true;
} else {
fprintf(stderr, "Unrecognized option %s\n", argv[j]);
usage();
Expand Down

0 comments on commit 60c6d6b

Please sign in to comment.