From bcd3ec760203f68abef1c1e2efe1bfc92aa5e225 Mon Sep 17 00:00:00 2001 From: Jeremy Maitin-Shepard Date: Fri, 3 Oct 2008 22:03:36 -0700 Subject: [PATCH] spawn-process: many bug fixes --- conkeror-spawn-helper.c | 36 +++++++++++++++++++++++++++++++----- modules/io.js | 22 +++++++++++++++++----- modules/spawn-process.js | 18 +++++++++++++++--- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/conkeror-spawn-helper.c b/conkeror-spawn-helper.c index 2c7c381..dcad86d 100644 --- a/conkeror-spawn-helper.c +++ b/conkeror-spawn-helper.c @@ -17,6 +17,7 @@ #include #include #include +#include void fail(const char *msg) { fprintf(stderr, "%s\n", msg); @@ -200,7 +201,7 @@ void setup_fds(struct fd_info *fds, int fd_count) { break; } } - TRY(result, dup2(fd, fds[i].orig_fd)); + TRY(result, dup2(fds[i].orig_fd, fd)); close(fds[i].orig_fd); } } @@ -224,8 +225,33 @@ int main(int argc, char **argv) { /* Block SIGPIPE to avoid a signal being generated while writing to a socket */ signal(SIGPIPE, SIG_IGN); - /* Close STDIN as we don't need it */ - close(STDIN_FILENO); + /* Close everything except STDERR. Mozilla leaves us with a bunch + of junk file descriptors. */ + { + DIR *dir = opendir("/proc/self/fd"); + if (!dir) { + /* No proc filesystem available, just loop through file descriptors */ + struct rlimit file_lim; + int max_fileno = 1024; + if (getrlimit(RLIMIT_NOFILE, &file_lim) == 0) + max_fileno = file_lim.rlim_cur; + for (i = 0; i < max_fileno; ++i) { + if (i == STDERR_FILENO) + continue; + close(i); + } + } else { + struct dirent *dir_ent; + int dir_fd = dirfd(dir); + while ((dir_ent = readdir(dir)) != NULL) { + int file_desc = atoi(dir_ent->d_name); + if (file_desc == STDERR_FILENO || file_desc == dir_fd) + continue; + close(file_desc); + } + closedir(dir); + } + } /* Parse key file */ { @@ -257,7 +283,7 @@ int main(int argc, char **argv) { for (i = 0; i < fd_count; ++i) { fds[i].desired_fd = atoi(next_term(&buf, &len)); fds[i].path = next_term(&buf, &len); - if (fds[i].path) { + if (fds[i].path[0]) { fds[i].open_mode = atoi(next_term(&buf, &len)); fds[i].perms = atoi(next_term(&buf, &len)); } @@ -275,7 +301,7 @@ int main(int argc, char **argv) { /* Create a socket connection or open a local file for each requested file descriptor redirection. */ for (i = 0; i < fd_count; ++i) { - if (fds[i].path) { + if (fds[i].path[0]) { TRY(fds[i].orig_fd, open(fds[i].path, fds[i].open_mode, fds[i].perms)); } else { fds[i].orig_fd = my_connect(port, client_key, fds[i].desired_fd); diff --git a/modules/io.js b/modules/io.js index 959ba46..8b7dc38 100644 --- a/modules/io.js +++ b/modules/io.js @@ -129,14 +129,16 @@ function binary_input_stream(stream) { return s; } -// callback is called with a single argument, either true if the write succeeded, or false otherwise +// callback is called with null if the write succeeded, and an error otherwise function async_binary_write(stream, data, callback) { + var data1 = data; function attempt_write() { try { while (true) { if (data.length == 0) { stream.flush(); - callback(true); + if (callback != null) + callback(null); return; } var len = stream.write(data, data.length); @@ -147,7 +149,8 @@ function async_binary_write(stream, data, callback) { } catch (e if (e instanceof Components.Exception) && e.result == Cr.NS_BASE_STREAM_WOULD_BLOCK) {} catch (e) { - callback(false); + if (callback != null) + callback(e); return; } output_stream_async_wait(stream, attempt_write, data.length); @@ -181,9 +184,18 @@ function decode_string(bstr, charset) { return converter.ConvertToUnicode(bstr); } -function async_binary_string_writer(bstr) { +/* Calls callback when the write has completed. If callback is null, + the stream is closed when the write completes. */ +function async_binary_string_writer(bstr, callback) { return function (stream) { - async_binary_write(stream, bstr); + function modified_callback (e) { + if (callback == null) { + stream.close(); + } else { + callback(e); + } + } + async_binary_write(stream, bstr, modified_callback); }; } diff --git a/modules/spawn-process.js b/modules/spawn-process.js index 32850aa..0a67156 100644 --- a/modules/spawn-process.js +++ b/modules/spawn-process.js @@ -193,6 +193,10 @@ function spawn_process(program_name, args, working_dir, for (let i in fds) { if (fds.hasOwnProperty(i)) { + if (fds[i] == null) { + delete fds[i]; + continue; + } key_file_fd_data += i + "\0"; let fd = fds[i]; if ('file' in fd) { @@ -200,8 +204,10 @@ function spawn_process(program_name, args, working_dir, fd.perms = 0666; key_file_fd_data += fd.file + "\0" + fd.mode + "\0" + fd.perms + "\0"; delete fds[i]; // Remove it from fds, as we won't need to work with it anymore - } else + } else { ++total_fds; + key_file_fd_data += "\0"; + } ++total_client_fds; } } @@ -431,7 +437,7 @@ function spawn_process(program_name, args, working_dir, var fd = parseInt(fdspec); if (!fds.hasOwnProperty(fd) || (fd in registered_transports)) throw "Invalid fd"; - bin_stream.close(); + remove_from_unregistered(); bin_stream = null; registered_transports[fd] = {transport: transport, input: in_stream, @@ -442,7 +448,9 @@ function spawn_process(program_name, args, working_dir, cleanup_server(); control_state = CONTROL_SENDING_KEY; async_binary_write(control_output_stream, server_key, - function () { + function (error) { + if (error != null) + fail(error); control_state = CONTROL_SENT_KEY; if (setup_timer) { setup_timer.cancel(); @@ -456,8 +464,12 @@ function spawn_process(program_name, args, working_dir, let t = registered_transports[i]; if ('input' in f) f.input(t.input); + else + t.input.close(); if ('output' in f) f.output(t.output); + else + t.output.close(); } } }); -- 2.11.4.GIT