demo
比如ros2 topic pub
就是一个可能不会自动结束的shell指令,在C++进行并发设计时,往往可能导致这些进程变成野进程
因此我们需要主动管理 / 退出他们
以下给出一个 基于 **close(pipe)**强行注销管道 以实现关闭进程的方法。
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <thread>
#include <sstream>
std::string command = R"(
ros2 topic pub /initialpose geometry_msgs/PoseWithCovarianceStamped "\
header:
stamp:
sec: 0,
nanosec: 0
frame_id: 'map'
pose:
pose:
position:
x: -2.0,
y: -0.5,
z: 0.0
orientation:
x: 0.0,
y: 0.0,
z: 0.01,
w: 1.0
covariance: [0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.06853891909122467]
" -1
)";
std::string command_1 = "ros2 topic echo /scan --full-length --once > ls.yaml";
std::vector<std::thread> thread_list;
bool SHUTDOWN_FLAG = false;
std::stringstream do_command(const std::string& command, bool if_stdout_ = false) {
std::stringstream result;
FILE* pipe = popen(command.c_str(), "r");
if (!pipe) {
std::cerr << "popen() failed!" << std::endl;
exit(1);
}
char buffer[128];
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != nullptr){
if (!if_stdout_) std::cout << buffer;
result << buffer;
}
if (SHUTDOWN_FLAG) break;
}
int status = pclose(pipe);
if (status == -1) {
std::cerr << "pclose() failed!" << std::endl;
exit(1);
}
return result;
}
inline void shutdown() {
SHUTDOWN_FLAG = true;
for (auto& thread : thread_list) {
if (thread.joinable())
thread.join();
}
}
int main() {
// 启动线程执行命令
thread_list.emplace_back(do_command, command, false); // 输出命令执行结果
// wait
for (int i = 0; i < 5; ++i) {
std::cout << "Main thread is doing task " << i << std::endl;
// 在这里添加其他任务代码
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟执行任务的耗时
}
shutdown();
return 0;
}
Futhermore
该方法仍有局限性:当面对没有输出反馈的终端指令时,依然会失去作用。
本人目前正在设计一种通用性更强的并发管理模板,满足执行终端指令时的多种需求:主动关闭不会自动结束的shell命令、读取命令反馈、stdout和stderr支持、阻塞和非阻塞状态均兼容等。
完美解决方案已给出
详情请见博客:下一篇博客