Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/subprocess-posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Subprocess::~Subprocess() {

bool Subprocess::Start(SubprocessSet* set, const string& command) {
int output_pipe[2];
int input_pipe[2] = { -1, -1 };
if (pipe(output_pipe) < 0)
Fatal("pipe: %s", strerror(errno));
fd_ = output_pipe[0];
Expand Down Expand Up @@ -119,10 +120,32 @@ bool Subprocess::Start(SubprocessSet* set, const string& command) {
Fatal("posix_spawnattr_setflags: %s", strerror(err));

const char* spawned_args[] = { "/bin/sh", "-c", command.c_str(), NULL };
if (!use_console_) {
if (pipe(input_pipe) < 0)
Fatal("pipe: %s", strerror(errno));
SetCloseOnExec(input_pipe[0]);
err = posix_spawn_file_actions_adddup2(&action, input_pipe[0], 0);
if (err != 0)
Fatal("posix_spawn_file_actions_adddup2: %s", strerror(err));
err = posix_spawn_file_actions_addclose(&action, input_pipe[0]);
if (err != 0)
Fatal("posix_spawn_file_actions_addclose: %s", strerror(err));
err = posix_spawn_file_actions_addclose(&action, input_pipe[1]);
if (err != 0)
Fatal("posix_spawn_file_actions_addclose: %s", strerror(err));
spawned_args[1] = NULL;
}
err = posix_spawn(&pid_, "/bin/sh", &action, &attr,
const_cast<char**>(spawned_args), environ);
if (err != 0)
Fatal("posix_spawn: %s", strerror(err));

if (!use_console_) {
ssize_t written = write(input_pipe[1], command.c_str(), command.size());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that work for large commands?

Most systems use a default pipe buffer size of 64 kiB, some even smaller (see https://github.com/afborchert/pipebuf) so this write() call will block infinitely if command.size() is larger than that (and the bug referenced by this PR talks about command sizes of 128 kiB).

Linux has fcntl(F_SETPIPE_SZ) to change that the pipe buffer size, but I am not aware of similar features on other systems. Even the Linux pipe manpage tsates that applications should not rely on a specific capacity.

It might be more portable and simple to write long commands to a file that is passed as the first argument to the shell instead. And that would also work for console processes too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

friendly ping?

if (written == -1)
Fatal("write to input pipe: %s", strerror(errno));
close(input_pipe[1]);
}

err = posix_spawnattr_destroy(&attr);
if (err != 0)
Expand Down
Loading