Boost :: обработать дочерний по идентификатору - PullRequest
1 голос
/ 16 апреля 2020

Как я могу получить child.id () в функции on_exit?

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

        }));

или как я могу проверить другие функции, если ребенок работает по идентификатору?

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

1 Ответ

0 голосов
/ 22 апреля 2020

Вы можете привязать любую дополнительную информацию к своему обработчику. Например, вы можете объявить, что ваш обработчик принимает ссылку на экземпляр child:

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

Теперь вы можете привязать это к обработчику on_exit, используя std::bind (конечно, вы можете использовать лямбда для выполнения этой работы):

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 дочерних процессов, выполнение которых занимает различное время <1 с, и все привязываются к одному и тому же обработчику: </p>

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() << ")\n";
}

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\n";
}

Отпечатки:

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 (будьте очень осторожны с эталонной стабильностью выбранного вами контейнера!).

Вот демонстрационная версия Live On Coliru

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\n";

Отпечатки

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
...