X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fexternal%2Fprocess-cpp-minimal%2Fsrc%2Fcore%2Fposix%2Ffork.cpp;fp=src%2Ftype3_AndroidCloud%2Fanbox-master%2Fexternal%2Fprocess-cpp-minimal%2Fsrc%2Fcore%2Fposix%2Ffork.cpp;h=82a225c706b14192e06a6def77ff0d3bc4aa16c3;hb=e26c1ec581be598521517829adba8c8dd23a768f;hp=0000000000000000000000000000000000000000;hpb=6699c1aea74eeb0eb400e6299079f0c7576f716f;p=iec.git diff --git a/src/type3_AndroidCloud/anbox-master/external/process-cpp-minimal/src/core/posix/fork.cpp b/src/type3_AndroidCloud/anbox-master/external/process-cpp-minimal/src/core/posix/fork.cpp new file mode 100644 index 0000000..82a225c --- /dev/null +++ b/src/type3_AndroidCloud/anbox-master/external/process-cpp-minimal/src/core/posix/fork.cpp @@ -0,0 +1,184 @@ +/* + * Copyright © 2013 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authored by: Thomas Voß + */ + +#include +#include + +#ifndef ANDROID +#include "backtrace.h" +#endif + +#include +#include +#include + +#include + +namespace +{ +void redirect_stream_to_fd(int fd, int stream) +{ + auto rc = ::dup2(fd, stream); + if (rc == -1) + throw std::system_error(errno, std::system_category()); +} + +void print_backtrace(std::ostream& out, const std::string& line_prefix) +{ +#ifndef ANDROID + core::posix::backtrace::visit_with_handler([&out, line_prefix](const core::posix::backtrace::Frame& frame) + { + out << line_prefix << std::dec << std::setw(2) << frame.depth() << "@" << std::hex << std::setw(14) << frame.frame_pointer() << ": " + << (frame.symbol().is_cxx() ? frame.symbol().demangled() : frame.symbol().raw()) << std::endl; + return true; + }); +#endif +} +} + +namespace core +{ +namespace posix +{ + +bool is_child(pid_t pid) { return pid == 0; } + +ChildProcess fork(const std::function& main, + const StandardStream& flags) +{ + ChildProcess::Pipe stdin_pipe{ChildProcess::Pipe::invalid()}; + ChildProcess::Pipe stdout_pipe{ChildProcess::Pipe::invalid()}; + ChildProcess::Pipe stderr_pipe{ChildProcess::Pipe::invalid()}; + + if ((flags & StandardStream::stdin) != StandardStream::empty) + stdin_pipe = ChildProcess::Pipe(); + if ((flags & StandardStream::stdout) != StandardStream::empty) + stdout_pipe = ChildProcess::Pipe(); + if ((flags & StandardStream::stderr) != StandardStream::empty) + stderr_pipe = ChildProcess::Pipe(); + + pid_t pid = ::fork(); + + if (pid == -1) + throw std::system_error(errno, std::system_category()); + + if (is_child(pid)) + { + posix::exit::Status result = posix::exit::Status::failure; + + try + { + stdin_pipe.close_write_fd(); + stdout_pipe.close_read_fd(); + stderr_pipe.close_read_fd(); + // We replace stdin and stdout of the child process first: + if ((flags & StandardStream::stdin) != StandardStream::empty) + redirect_stream_to_fd(stdin_pipe.read_fd(), STDIN_FILENO); + if ((flags & StandardStream::stdout) != StandardStream::empty) + redirect_stream_to_fd(stdout_pipe.write_fd(), STDOUT_FILENO); + if ((flags & StandardStream::stderr) != StandardStream::empty) + redirect_stream_to_fd(stderr_pipe.write_fd(), STDERR_FILENO); + + result = main(); + } catch(const std::exception& e) + { + std::cerr << "core::posix::fork(): An unhandled std::exception occured in the child process:" << std::endl + << " what(): " << e.what() << std::endl; + print_backtrace(std::cerr, " "); + } catch(...) + { + std::cerr << "core::posix::fork(): An unhandled exception occured in the child process." << std::endl; + print_backtrace(std::cerr, " "); + } + + // We have to ensure that we exit here. Otherwise, we run into + // all sorts of weird issues. + ::exit(static_cast(result)); + } + + // We are in the parent process, and create a process object + // corresponding to the newly forked process. + stdin_pipe.close_read_fd(); + stdout_pipe.close_write_fd(); + stderr_pipe.close_write_fd(); + + return ChildProcess(pid, + stdin_pipe, + stdout_pipe, + stderr_pipe); +} + +ChildProcess vfork(const std::function& main, + const StandardStream& flags) +{ + ChildProcess::Pipe stdin_pipe, stdout_pipe, stderr_pipe; + + pid_t pid = ::vfork(); + + if (pid == -1) + throw std::system_error(errno, std::system_category()); + + if (is_child(pid)) + { + posix::exit::Status result = posix::exit::Status::failure; + + try + { + // We replace stdin and stdout of the child process first: + stdin_pipe.close_write_fd(); + stdout_pipe.close_read_fd(); + stderr_pipe.close_read_fd(); + // We replace stdin and stdout of the child process first: + if ((flags & StandardStream::stdin) != StandardStream::empty) + redirect_stream_to_fd(stdin_pipe.read_fd(), STDIN_FILENO); + if ((flags & StandardStream::stdout) != StandardStream::empty) + redirect_stream_to_fd(stdout_pipe.write_fd(), STDOUT_FILENO); + if ((flags & StandardStream::stderr) != StandardStream::empty) + redirect_stream_to_fd(stderr_pipe.write_fd(), STDERR_FILENO); + + result = main(); + } catch(const std::exception& e) + { + std::cerr << "core::posix::fork(): An unhandled std::exception occured in the child process:" << std::endl + << " what(): " << e.what() << std::endl; + print_backtrace(std::cerr, " "); + } catch(...) + { + std::cerr << "core::posix::fork(): An unhandled exception occured in the child process." << std::endl; + print_backtrace(std::cerr, " "); + } + + // We have to ensure that we exit here. Otherwise, we run into + // all sorts of weird issues. + ::exit(static_cast(result)); + } + + // We are in the parent process, and create a process object + // corresponding to the newly forked process. + // Close the parent's pipe end + stdin_pipe.close_read_fd(); + stdout_pipe.close_write_fd(); + stderr_pipe.close_write_fd(); + + return ChildProcess(pid, + stdin_pipe, + stdout_pipe, + stderr_pipe); +} +} +}