c++ - 终止 C++ 中的线程及其产生的任何进程

标签 c++ multithreading process kill pid

我正在 Linux 上用 C++ 编写一个模糊器。它产生多个线程,并在线程因任何原因挂起时具有超时功能。在计时器用完后,我无法找出终止线程的正确方法。我现在正在做的是:

`
#include <signal.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <chrono>
#include <thread>
#include <stdlib.h>
#include <sys/wait.h>
#include <stdio.h>
#include <vector>
#include <iostream>
#include <sys/time.h>
#include <random>
#include <cstdlib>
#include <climits>
#include <sstream>
#include <iomanip>
#include <unistd.h>
#include <cstring>

#define READ   0
#define WRITE  1



void reaper (int c_pid, int t_timeout) {
  std::this_thread::sleep_for(std::chrono::milliseconds(t_timeout));
  kill (c_pid, 9);
}


FILE * popen2 (std::string command, std::string type, int & pid, std::string low_lvl_user) {
  pid_t child_pid;
  int fd[2];
  pipe(fd);
  if((child_pid = fork()) == -1) {
    perror("fork");
    exit(1);
  }
  if (child_pid == 0) {  // child begins
    if (type == "r") {
      close(fd[READ]);    //Close the READ
      dup2(fd[WRITE], 1); //Redirect stdout to pipe
    }
    else {
      close(fd[WRITE]);    //Close the WRITE
      dup2(fd[READ], 0);   //Redirect stdin to pipe
    }
    if (getuid() == 0) {
      execl("/bin/su", "su", "-c", "/bin/sh", "-c", command.c_str(), low_lvl_user.c_str(), NULL);  // fixes not being able to reap suid 0 processes
    }
    else {
      execl("/bin/sh", "/bin/sh", "-c", command.c_str(), NULL); // runs it all
    }
    exit(0);
  }
  else {
    if (type == "r") {
      close(fd[WRITE]); //Close the WRITE
    }
    else {
      close(fd[READ]); //Close the READ
    }
  }
  pid = child_pid;
  if (type == "r") {
    return fdopen(fd[READ], "r");
  }
  return fdopen(fd[WRITE], "w");
}


int pclose2(FILE * fp, pid_t pid) // close it so we don't fuck outselves
{
  int stat;
  fclose(fp);
  while (waitpid(pid, &stat, 0) == -1) {
    if (errno != EINTR) {
      stat = -1;
      break;
    }
  }
  return stat;
}


int spawn_ch (std::string out_str) {
  std::string low_lvl_user = "nobody";
  int t_timeout = 500;
      int pid;  // initializes child
      FILE * fp = popen2(out_str, "r", pid, low_lvl_user); // opens child process fork
      char command_out[4096] = {0};
      std::stringstream output;
      std::thread reaper_thread(reaper, pid, t_timeout);  // takes care of killing it off if it takes too long
      reaper_thread.join();
      while (read(fileno(fp), command_out, sizeof(command_out)-1) != 0) {
        output << std::string(command_out);
        memset(&command_out, 0, sizeof(command_out));
      }
      pclose2(fp, pid);
      std::string token;
}


int main () {
  std::string command = "HOME=AAAAAAAAA MAIL=AA  /usr/sbin/exim4 -Ac AAAAAA -G   -MCP,9,-Mar  -Mf  -Mset b -S 999999  -X,,-bF 999 -bdf  -bpc  -bpr   -bpru,,-bt   -exim4,AAA, -f,AAAAAAAAA,-oA   -oMa,5Mu^i, -oMaa,, -oMas,,-oMs  -oX isotanr -odb  -oee   -oem,999, -oo,99999999 -r 999999999 -t  -ti 999999";
  std::vector<std::thread> threads;
  int num_threads = 2;
  for (int cur_thread=1; cur_thread <= num_threads; ++cur_thread) threads.push_back(std::thread(spawn_ch, command));  // Thrift Shop
  for (auto& all_thread : threads) all_thread.join();  // is that your grandma's coat?
  exit(0);
}

但是由于在这个例子中进程被生成为 suid 101(或 0,或其他任何东西),kill 函数可以作为 root 运行以获取它生成的进程......这会起作用,除了 exim4 显然试图产生多个进程,当一个进程死亡时,其他进程不会。有没有办法让程序知道产生了哪些进程来杀死它们,或者最好是终止产生它们的整个线程的方法(我认为这应该有效,就好像你 ctrl+c 我的程序它会杀死它产生了什么)?

整个代码库在 github 上.

提前致谢。

最佳答案

std::thread 类不提供任意终止事件执行线程的方法。此功能未在当前 C++ 标准中实现。

您发布的示例代码几乎是唯一可以完全使用 C++ 和 C 库中的功能完成的事情。

POSIX 线程 API 是另一种选择。它确实提供了终止事件线程的方法;然而,它伴随着许多重要的警告,并且很难避免未定义的行为,当使用 pthread_cancel() 终止执行线程时,因为这不会正确地展开终止线程的堆栈,并调用所有需要的析构函数;此外,执行线程必须到达取消点,以便 pthread_cancel() 生效。

此外,如果执行线程执行另一个进程,新进程将替换线程的整个进程,而不仅仅是执行线程的上下文。如果这一直是您的意图,那么尝试取消线程无论如何都不会有太大好处,您几乎必须做您已经在做的事情。

关于c++ - 终止 C++ 中的线程及其产生的任何进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31772948/

相关文章:

c++ - 我无法理解这段代码

c++ - Window C/C++ Crypto API 示例和提示

c# - WindowsMediaPlayer (WMPLib) 音频突然消失

c - 通过pid查找task_struct的有效方法

ios - 在iOS上,如何在产生数据的线程上实现阻塞或 "being blocked"?

java - 使我的应用程序能够自行获取辅助功能权限

c++ - C 和 C++ 中 sizeof 运算符的不同输出

c++ - Ctrl + Z 无法退出 while 循环

java - C程序在哪个线程中执行?

c# - 带参数调用委托(delegate)方法名