From f61269a0177a4b381f10a6773dfa9b8f47dd51ca Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 3 Nov 2015 03:58:18 +0400 Subject: [PATCH] more reliable tmuxspawn for output tabs --- node_modules/vfs-local/localfs.js | 138 +++++++++------------ plugins/c9.ide.terminal/tmux_connection.js | 2 + 2 files changed, 62 insertions(+), 78 deletions(-) diff --git a/node_modules/vfs-local/localfs.js b/node_modules/vfs-local/localfs.js index f9376f77..e87d023f 100644 --- a/node_modules/vfs-local/localfs.js +++ b/node_modules/vfs-local/localfs.js @@ -1445,17 +1445,8 @@ module.exports = function setup(fsOptions) { function spawn(executablePath, options, callback) { var args = options.args || []; - - if (options.hasOwnProperty('env')) { - options.env.__proto__ = fsOptions.defaultEnv; - } else { - options.env = fsOptions.defaultEnv; - } - if (options.cwd && options.cwd.charAt(0) == "~") - options.cwd = options.env.HOME + options.cwd.substr(1); - if (transformPath && options.cwd) - options.cwd = transformPath(options.cwd); + _setDefaultEnv(options); resolvePath(executablePath, { nocheck : 1, @@ -1492,25 +1483,8 @@ module.exports = function setup(fsOptions) { var args = options.args || []; delete options.args; - if (options.hasOwnProperty('env')) { - options.env.__proto__ = fsOptions.defaultEnv; - } else { - options.env = fsOptions.defaultEnv; - } - - // Pty is only reading from the object itself; - var env = {}; - for (var prop in options.env) { - if (prop == "TMUX") continue; - env[prop] = options.env[prop]; - } - options.env = env; - - if (options.cwd && options.cwd.charAt(0) == "~") - options.cwd = env.HOME + options.cwd.substr(1); - - if (transformPath && options.cwd) - options.cwd = transformPath(options.cwd); + _setDefaultEnv(options); + delete options.env.TMUX; if (options.testing) { args.forEach(function(arg, i){ @@ -1767,7 +1741,7 @@ module.exports = function setup(fsOptions) { // logToFile("Kill: " + options.session); _execFile(TMUX, - ["-L", tmuxName, "kill-session", "-t", options.session], + ["-L", tmuxName, "-C", "kill-session", "-t", options.session], function(err){ if (!options.command) return callback(err, {}); @@ -1843,33 +1817,34 @@ module.exports = function setup(fsOptions) { + "rm '" + watchFile + "')"); args.push( - ";", "set-option", "-g", "status", "off", - ";", "set-option", "destroy-unattached", "off", - ";", "set-option", "mouse-select-pane", "on", - ";", "set-option", "set-titles", "on", - ";", "set-option", "quiet", "off", - ";", "set-option", "-g", "prefix", "C-b", - ";", "set-option", "-g", "terminal-overrides", "'xterm:colors=256'" + ";", "set", "-q", "-g", "status", "off", + ";", "set", "-q", "destroy-unattached", "off", + ";", "set", "-q", "mouse-select-pane", "on", + ";", "set", "-q", "set-titles", "on", + ";", "set", "-q", "quiet", "on", + ";", "set", "-q", "-g", "prefix", "C-b", + ";", "set", "-q", "-g", "terminal-overrides", "'xterm:colors=256'" ); // disable buffering of tmux output // TODO investigate if using capture pane after desync is faster - args.push(";", "set-window-option", "c0-change-trigger", "0"); + args.push(";", "setw", "c0-change-trigger", "0"); if (options.output) { args.push( - ";", "set-option", "remain-on-exit", "on", - ";", "set-window-option", "-g", "aggressive-resize", "on" + ";", "set", "-q", "remain-on-exit", "on", + ";", "setw", "-q", "-g", "aggressive-resize", "on" ); } + + if (options.detach && options.output) { + args.unshift("-C"); + args.push(";", "list-panes", "-F", "c9-pid#{pane_pid}-"); + } if (options.detach) args.push(";", "detach"); - var quotedArgs = args.map(function(arg) { - return "'" + arg.replace(/'/g, "'\\''") + "'"; - }).join(" "); - options.env["LD_LIBRARY_PATH"] = (options.env["LD_LIBRARY_PATH"] ? options.env["LD_LIBRARY_PATH"] + ":" : "") + "~/.c9/local/lib"; @@ -1888,20 +1863,32 @@ module.exports = function setup(fsOptions) { else run(); }); } - else + else { run(); - + } + function run(err){ if (err) return callback(err); - // Start PTY with TMUX, in a login shell (when not attached) - var EXEC = attach ? TMUX : BASH; - var ARGS = attach - ? args - : [ "-l", "-c", "'" + TMUX + "' " + quotedArgs + " 2> /dev/null"]; + if (options.detach && options.output) { + _setDefaultEnv(options); + delete options.env.TMUX; + + return _execFile(TMUX, args, { + args: args, + name: options.name, + cwd: options.cwd, + resolve: options.resolve, + env: options.env + }, function(err, stdout) { + var m = /c9-pid(\d+)-/.exec(stdout); + var pid = parseInt(m && m[1], 10); + callback(err, {pid: pid}); + }); + } - ptyspawn(EXEC, { - args: ARGS, + ptyspawn(TMUX, { + args: args, name: options.name, cols: options.cols, rows: options.rows, @@ -1923,26 +1910,10 @@ module.exports = function setup(fsOptions) { err.code = "EPERM"; meta.pty.emit("data", err); } - else if (data) { - // Fetch the PID if appropriate - if (options.detach && options.output) { - fetchPid(function(err, pid){ - if (err) return callback(err); - meta.pid = pid.pid; - callback(null, meta); - }); - - if (process.platform != "win32") - meta.pty.kill(); - } - meta.pty.removeListener("data", wait); } }); - - if (options.detach && options.output) - return; } // Return the pty @@ -2220,16 +2191,8 @@ module.exports = function setup(fsOptions) { function execFile(executablePath, options, callback) { if (isWin && execFileWin(executablePath, options, callback)) return; - if (options.hasOwnProperty('env')) { - options.env.__proto__ = fsOptions.defaultEnv; - } else { - options.env = fsOptions.defaultEnv; - } - if (options.cwd && options.cwd.charAt(0) == "~") - options.cwd = options.env.HOME + options.cwd.substr(1); - if (transformPath && options.cwd) - options.cwd = transformPath(options.cwd); + _setDefaultEnv(options); resolvePath(executablePath, { nocheck : 1, @@ -2268,6 +2231,25 @@ module.exports = function setup(fsOptions) { return true; } } + + function _setDefaultEnv(options) { + if (options.hasOwnProperty("env")) + options.env.__proto__ = fsOptions.defaultEnv; + else + options.env = fsOptions.defaultEnv; + + // Pty is only reading from the object itself; + var env = {}; + for (var prop in options.env) + env[prop] = options.env[prop]; + options.env = env; + + if (options.cwd && options.cwd.charAt(0) == "~") + options.cwd = options.env.HOME + options.cwd.substr(1); + + if (transformPath && options.cwd) + options.cwd = transformPath(options.cwd); + } function killtree(pid, options, callback) { var code = options.code || options.graceful ? "SIGTERM" : "SIGKILL"; diff --git a/plugins/c9.ide.terminal/tmux_connection.js b/plugins/c9.ide.terminal/tmux_connection.js index e1a25459..9b22a2a4 100644 --- a/plugins/c9.ide.terminal/tmux_connection.js +++ b/plugins/c9.ide.terminal/tmux_connection.js @@ -84,6 +84,8 @@ module.exports = function(c9, proc, installPath, shell) { getOutputHistory(options, cb); }, options.retries * 100 + 300); } + if (buffer) + buffer = buffer.replace(/\s*\x1b\[1mPane is dead\x1b\[0m\s*$/, "\n"); cb(errBuffer, buffer); }); });