Skip to content

Commit

Permalink
Allow detaching of run-process (#1434)
Browse files Browse the repository at this point in the history
  • Loading branch information
wolfv authored Feb 7, 2022
1 parent a7d7498 commit 60d4b3a
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 1 deletion.
3 changes: 3 additions & 0 deletions micromamba/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ endif ()

message(STATUS "Micromamba linkage: ${MICROMAMBA_LINKAGE}")

find_package(Threads REQUIRED)
target_link_libraries(micromamba PRIVATE Threads::Threads)

if (${MICROMAMBA_LINKAGE} STREQUAL "FULL_STATIC")
target_link_libraries(micromamba PRIVATE libmamba-full-static)
if (WIN32)
Expand Down
117 changes: 116 additions & 1 deletion micromamba/src/run.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,67 @@
#include <csignal>

#include <reproc++/run.hpp>
#include "common_options.hpp"

#include "mamba/api/configuration.hpp"
#include "mamba/api/install.hpp"

#ifndef _WIN32
extern "C" {
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
}
#endif

using namespace mamba; // NOLINT(build/namespaces)

#ifndef _WIN32
void daemonize()
{
pid_t pid, sid;
int fd;

// already a daemon
if (getppid() == 1)
return;

// fork parent process
pid = fork();
if (pid < 0)
exit(1);

// exit parent process
if (pid > 0)
exit(0);

// at this point we are executing as the child process
// create a new SID for the child process
sid = setsid();
if (sid < 0)
exit(1);

fd = open("/dev/null", O_RDWR, 0);

std::cout << fmt::format("Kill process with: kill {}", getpid()) << std::endl;

if (fd != -1)
{
dup2 (fd, STDIN_FILENO);
dup2 (fd, STDOUT_FILENO);
dup2 (fd, STDERR_FILENO);

if (fd > 2)
{
close (fd);
}
}
}
#endif

void
set_run_command(CLI::App* subcom)
{
Expand All @@ -18,15 +73,29 @@ set_run_command(CLI::App* subcom)
static std::string cwd;
subcom->add_option("--cwd", cwd, "Current working directory for command to run in. Defaults to cwd");

static bool detach = false;
#ifndef _WIN32
subcom->add_flag("-d,--detach", detach, "Detach process from terminal");
#endif

static std::vector<std::string> command;
subcom->prefix_command();

static reproc::process proc;

subcom->callback([subcom, stream_option]() {
auto& config = Configuration::instance();
config.load();

std::vector<std::string> command = subcom->remaining();


// replace the wrapping bash with new process entirely
#ifndef _WIN32
if (command.front() != "exec")
command.insert(command.begin(), "exec");
#endif

auto [wrapped_command, script_file]
= prepare_wrapped_call(Context::instance().target_prefix, command);

Expand All @@ -44,11 +113,57 @@ set_run_command(CLI::App* subcom)

opt.redirect.out.type = sinkout ? reproc::redirect::discard : reproc::redirect::parent;
opt.redirect.err.type = sinkerr ? reproc::redirect::discard : reproc::redirect::parent;
auto [_, ec] = reproc::run(wrapped_command, opt);

#ifndef _WIN32
if (detach)
{
std::cout << fmt::format(fmt::fg(fmt::terminal_color::green), "Running wrapped script {} in the background", join(" ", command)) << std::endl;
daemonize();
}
#endif

int status, pid;
std::error_code ec;

ec = proc.start(wrapped_command, opt);

std::tie(pid, ec) = proc.pid();

if (ec)
{
std::cerr << ec.message() << std::endl;
exit(1);
}

#ifndef _WIN32
std::thread t([](){
signal(SIGTERM, [](int signum) {
std::cout << "Received SIGTERM on micromamba run - terminating process" << std::endl;
reproc::stop_actions sa;
sa.first = reproc::stop_action{reproc::stop::terminate, std::chrono::milliseconds(3000)};
sa.second = reproc::stop_action{reproc::stop::kill, std::chrono::milliseconds(3000)};
proc.stop(sa);
});
});
t.detach();
#endif

// check if we need this
if (!opt.redirect.discard && opt.redirect.file == nullptr &&
opt.redirect.path == nullptr) {
opt.redirect.parent = true;
}

ec = reproc::drain(proc, reproc::sink::null, reproc::sink::null);

std::tie(status, ec) = proc.stop(opt.stop);

if (ec)
{
std::cerr << ec.message() << std::endl;
}

// exit with status code from reproc
exit(status);
});
}

0 comments on commit 60d4b3a

Please sign in to comment.