Boost::process child by id

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Boost::process child by id相关的知识,希望对你有一定的参考价值。

如何在on_exit函数中获取child.id()?

bp::child c(args, ios, bp::on_exit([&](int e, std::error_code ec) {
            result = e;
            ios.stop();
            //need c.id();    

        }));

或者我如何在其他函数中通过id检查子函数是否在运行?

        boost::process::child c(data->id); // doesn't work
        if (!c.running()) {
}
答案

你可以将任何你想要的额外信息绑定到你的处理程序中。例如,你可以声明你的处理程序采用一个对 child 的例子。

static void exit_handler(bp::child& process, int e, std::error_code ec) {
    std::cout << "Process " << process.id() << " exited with " << e << " (" << ec.message() << ")
";
}

现在,你可以把它绑定到 on_exit 处理程序,使用 std::bind 当然你也可以用lambda来完成这项工作)。

p = bp::child(
        sv{"/bin/bash", "-c", command.str()},
        bp::on_exit(std::bind(exit_handler, std::ref(p), _1, _2)),
        io);

// Or, using a lambda to capture the reference:
p = bp::child(
        sv{"/bin/bash", "-c", command.str()},
        bp::on_exit([&p](int e, std::error_code ec) { exit_handler(p, e, ec); }),
        io);

一个完整的例子,它产生了11个子进程,它们需要不同的时间< 1s来完成,并且都绑定到同一个处理程序。

Live On Coliru

#include <boost/process.hpp>
#include <boost/process/async.hpp>
#include <iostream>
#include <functional> // std::bind & placeholders
#include <sstream>    // ostringstream

namespace bp = boost::process;
using namespace std::placeholders;
using sv = std::vector<std::string>;

static void exit_handler(bp::child& process, int e, std::error_code ec) {
    std::cout << "Process " << process.id() << " exited with " << e << " (" << ec.message() << ")
";
}

int main() {
    boost::asio::io_context io;
    auto work = make_work_guard(io);

    std::list<bp::child> children;

    for (auto ch = 'a'; ch < 'k'; ++ch) {
        auto& p = children.emplace_back();
        std::ostringstream command;
        command << "echo 'hello from " << ch << "';";
        command << "sleep 0.$RANDOM;";
        command << "echo 'bye from " << ch << "';";
        command << "exit " << (rand()%42) << ";";

        p = bp::child(
                sv{"/bin/bash", "-c", command.str()},
                bp::on_exit(std::bind(exit_handler, std::ref(p), _1, _2)),
                io);
    }

    work.reset(); // allow io to be finished
    io.run();     // wait for that

    std::cout << "Bye
";
}

印刷品。

hello from b
hello from a
hello from c
hello from d
hello from e
hello from f
hello from g
hello from i
hello from h
hello from j
bye from g
bye from a
bye from h
bye from b
bye from d
bye from f
bye from j
bye from e
bye from i
bye from c
Process 12044 exited with 10 (Success)
Process 12034 exited with 1 (Success)
Process 12047 exited with 30 (Success)
Process 12035 exited with 4 (Success)
Process 12038 exited with 19 (Success)
Process 12043 exited with 31 (Success)
Process 12050 exited with 31 (Success)
Process 12042 exited with 29 (Success)
Process 12049 exited with 15 (Success)
Process 12036 exited with 9 (Success)
Bye

更新

为了能够查询哪个子代还在运行,可以考虑使用 map 而非 list (要非常小心你选择的容器的引用稳定性!)。

这里有一个演示 活在科利鲁

std::map<char, bp::child> children;

for (char name = 'a'; name < 'k'; ++name) {
    std::ostringstream command;
    command << "echo 'hello from " << name << "';";
    command << "sleep " << (rand()%900 + 101)/1000.0 << ";";
    command << "echo 'bye from " << name << "';";
    command << "exit " << (rand()%42) << ";";

    auto& p = children[name];
    p = bp::child(
            sv{"/bin/sh", "-c", command.str()},
            bp::on_exit(std::bind(exit_handler, std::ref(p), _1, _2)),
            io);
}

work.reset(); // allow io to be finished

while (io.run_one()) { // wait for that
    std::cout << "Still running: ";
    for (auto& [name, child] : children) {
        if (child.running())
            std::cout << " " << name;
    }
    std::cout << std::endl;
}

std::cout << "Bye
";

印刷品

hello from a
hello from b
hello from c
hello from d
hello from e
hello from f
hello from g
hello from h
hello from i
Still running:  a b c d e f g h i j
Still running:  a b c d e f g h i j
hello from j
bye from i
Still running:  a b c d e f g h j
Process 30748 exited with -1
Still running:  a b c d e f g h j
bye from e
Still running:  a b c d f g h j
Still running:  a b c d f g h j
Process 30739 exited with -1
Still running:  a b c d f g h j
bye from c
Still running:  a b d f g h j
Still running:  a b d f g h j
Process 30735 exited with -1
Still running:  a b d f g h j
bye from b
Still running:  a d f g h j
Still running:  a d f g h j
Process 30733 exited with -1
Still running:  a d f g h j
bye from h
Still running:  a d f g j
Still running:  a d f g j
Process 30744 exited with -1
Still running:  a d f g j
bye from d
Still running:  a f g j
Still running:  a f g j
Process 30737 exited with -1
Still running:  a f g j
bye from g
Still running:  a f j
Still running:  a f j
Process 30743 exited with -1
Still running:  a f j
bye from f
Still running:  a j
Still running:  a j
Process 30740 exited with -1
Still running:  a j
bye from j
Still running:  a
Still running:  a
Process 30749 exited with -1
Still running:  a
bye from a
Still running: 
Still running: 
Process 30732 exited with -1
Still running: 
Bye

以上是关于Boost::process child by id的主要内容,如果未能解决你的问题,请参考以下文章

提升进程 running() 和 exit_code() 线程安全

Boost 进程在新窗口中打开进程 (Windows)

Boost.Process - 如何让一个进程运行一个函数?

带有标准输出重定向的`boost :: process`在Ubuntu 16中随机失败

如何使用 Boost.Process 从“类型”(Windows)获取跟踪?

Windows 上的 Boost::process - 使用 MinGW?