    for (auto & s : seq)
        s.on_setup(*this);

    if (error())
    {
        for (auto & s : seq)
           s.on_error(*this, error());
        return child();
    }

    pid = fork()
    on_setup(*this);

    if (pid == -1) //fork error
    {
        set_error(get_last_error());
        for (auto & s : seq)
            s.on_fork_error(*this, error());
        for (auto & s : seq)
            s.on_error(*this, error());
        return child()
    }
    else if (pid == 0) //child process
    {
        for (auto & s : seq)
            s.on_exec_setup(*this);
        execve(exe, cmd_line, env);
        auto ec = get_last_error();
        for (auto & s : seq)
            s.on_exec_error(*this);

        unspecified();//here the error is send to the father process interally

        std::exit(EXIT_FAILURE);
        return child(); //for C++ compliance
    }

    child c(pid, exit_code);

    unspecified();//here, we read the the error from the child process

    if (error())
        for (auto & s : seq)
            s.on_error(*this, error());
    else
        for (auto & s : seq)
            s.on_success(*this);

    //now we check again, because a on_success handler might've errored.
    if (error())
    {
        for (auto & s : seq)
            s.on_error(*this, error());
        return child();
    }
    else
        return c;