mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 08:45:09 +00:00
Shell: Moves pipelined processes to one process group
This commit is contained in:
parent
8a17527bc5
commit
ab3e787334
6 changed files with 44 additions and 11 deletions
|
@ -1142,6 +1142,14 @@ RefPtr<Value> Pipe::run(RefPtr<Shell> shell)
|
|||
last_in_left.should_wait = false;
|
||||
last_in_left.is_pipe_source = true;
|
||||
|
||||
if (first_in_right.pipeline) {
|
||||
last_in_left.pipeline = first_in_right.pipeline;
|
||||
} else {
|
||||
auto pipeline = adopt(*new Pipeline);
|
||||
last_in_left.pipeline = pipeline;
|
||||
first_in_right.pipeline = pipeline;
|
||||
}
|
||||
|
||||
Vector<Command> commands;
|
||||
commands.append(left);
|
||||
commands.append(last_in_left);
|
||||
|
|
|
@ -150,9 +150,15 @@ private:
|
|||
virtual bool is_fd_redirection() const override { return true; }
|
||||
};
|
||||
|
||||
class Pipeline : public RefCounted<Pipeline> {
|
||||
public:
|
||||
pid_t pgid { -1 };
|
||||
};
|
||||
|
||||
struct Command {
|
||||
Vector<String> argv;
|
||||
NonnullRefPtrVector<Redirection> redirections;
|
||||
mutable RefPtr<Pipeline> pipeline;
|
||||
bool should_wait { true };
|
||||
bool is_pipe_source { false };
|
||||
bool should_notify_if_in_background { true };
|
||||
|
@ -190,7 +196,7 @@ public:
|
|||
}
|
||||
|
||||
CommandValue(Vector<String> argv)
|
||||
: m_command({ move(argv), {}, true, false, true })
|
||||
: m_command({ move(argv), {}, {}, true, false, true })
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -32,5 +32,6 @@ namespace AST {
|
|||
class Node;
|
||||
class Value;
|
||||
class SyntaxError;
|
||||
class Pipeline;
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "Job.h"
|
||||
#include "AST.h"
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/wait.h>
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Execution.h"
|
||||
#include "Forward.h"
|
||||
#include <AK/Function.h>
|
||||
#include <AK/JsonObject.h>
|
||||
#include <AK/JsonValue.h>
|
||||
|
@ -42,7 +43,7 @@
|
|||
|
||||
class Job : public RefCounted<Job> {
|
||||
public:
|
||||
static NonnullRefPtr<Job> create(pid_t pid, pid_t pgid, String command, u64 job_id) { return adopt(*new Job(pid, pgid, move(command), job_id)); }
|
||||
static NonnullRefPtr<Job> create(pid_t pid, pid_t pgid, String command, u64 job_id, AST::Pipeline* pipeline = nullptr) { return adopt(*new Job(pid, pgid, move(command), job_id, pipeline)); }
|
||||
|
||||
~Job()
|
||||
{
|
||||
|
@ -121,12 +122,15 @@ public:
|
|||
bool print_status(PrintStatusMode);
|
||||
|
||||
private:
|
||||
Job(pid_t pid, unsigned pgid, String cmd, u64 job_id)
|
||||
Job(pid_t pid, unsigned pgid, String cmd, u64 job_id, AST::Pipeline* pipeline)
|
||||
: m_pgid(pgid)
|
||||
, m_pid(pid)
|
||||
, m_job_id(job_id)
|
||||
, m_cmd(move(cmd))
|
||||
{
|
||||
if (pipeline)
|
||||
m_pipeline = *pipeline;
|
||||
|
||||
set_running_in_background(false);
|
||||
m_command_timer.start();
|
||||
}
|
||||
|
@ -143,4 +147,5 @@ private:
|
|||
mutable bool m_active { true };
|
||||
mutable bool m_is_suspended { false };
|
||||
bool m_should_be_disowned { false };
|
||||
RefPtr<AST::Pipeline> m_pipeline;
|
||||
};
|
||||
|
|
|
@ -518,15 +518,10 @@ RefPtr<Job> Shell::run_command(const AST::Command& command)
|
|||
perror("fork");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (child == 0) {
|
||||
setpgid(0, 0);
|
||||
tcsetattr(0, TCSANOW, &default_termios);
|
||||
if (command.should_wait) {
|
||||
auto pid = getpid();
|
||||
auto pgid = getpgid(pid);
|
||||
tcsetpgrp(STDOUT_FILENO, pgid);
|
||||
tcsetpgrp(STDIN_FILENO, pgid);
|
||||
}
|
||||
|
||||
for (auto& rewiring : rewirings) {
|
||||
#ifdef SH_DEBUG
|
||||
dbgprintf("in %s<%d>, dup2(%d, %d)\n", argv[0], getpid(), rewiring.dest_fd, rewiring.source_fd);
|
||||
|
@ -572,10 +567,27 @@ RefPtr<Job> Shell::run_command(const AST::Command& command)
|
|||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
bool is_first = !command.pipeline || (command.pipeline && command.pipeline->pgid == -1);
|
||||
|
||||
if (command.pipeline) {
|
||||
if (is_first) {
|
||||
command.pipeline->pgid = child;
|
||||
}
|
||||
}
|
||||
|
||||
pid_t pgid = is_first ? child : (command.pipeline ? command.pipeline->pgid : child);
|
||||
if (setpgid(child, pgid) < 0)
|
||||
perror("setpgid");
|
||||
|
||||
if (command.should_wait) {
|
||||
tcsetpgrp(STDOUT_FILENO, pgid);
|
||||
tcsetpgrp(STDIN_FILENO, pgid);
|
||||
}
|
||||
|
||||
StringBuilder cmd;
|
||||
cmd.join(" ", command.argv);
|
||||
|
||||
auto job = Job::create(child, (unsigned)child, cmd.build(), find_last_job_id() + 1);
|
||||
auto job = Job::create(child, pgid, cmd.build(), find_last_job_id() + 1, command.pipeline);
|
||||
jobs.set((u64)child, job);
|
||||
|
||||
job->on_exit = [](auto job) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue