From 126d343dea6b416b110543c0f0a60e5fa3302e19 Mon Sep 17 00:00:00 2001 From: Ruben Daniels <ruben@c9.io> Date: Tue, 21 May 2013 18:33:42 +0200 Subject: [PATCH 01/12] * Added PTY support --- consumer.js | 32 ++++++++++++++++++++++++++------ package.json | 2 +- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/consumer.js b/consumer.js index 6d84985..0c0e984 100644 --- a/consumer.js +++ b/consumer.js @@ -1,6 +1,6 @@ ( // Module boilerplate to support browser globals, node.js and AMD. (typeof module !== "undefined" && function (m) { module.exports = m(require('stream'), require('events'), require('smith')); }) || - (typeof define === "function" && function (m) { define("vfs-socket/consumer", ["./stream-amd", "./events-amd", "smith"], m); }) || + (typeof define === "function" && function (m) { define(["./stream-amd", "./events-amd", "smith"], m); }) || (function (m) { window.consumer = m(window.stream, window.events, window.smith); }) )(function (stream, events, smith) { "use strict"; @@ -74,6 +74,7 @@ function Consumer() { watch: route("watch"), connect: route("connect"), spawn: route("spawn"), + pty: route("pty"), execFile: route("execFile"), extend: route("extend"), unextend: route("unextend"), @@ -124,6 +125,10 @@ function Consumer() { proxyApi.emit("error", err); }); }); + + this.on("error", function(err){ + this.emit("error", err); + }) var nextStreamID = 1; function storeStream(stream) { @@ -137,9 +142,9 @@ function Consumer() { stream.pause && stream.pause(); } }); - stream.on("end", function () { + stream.on("end", function (chunk) { delete streams[id]; - remote.onEnd(id); + remote.onEnd(id, chunk); nextStreamID = id; }); } @@ -194,6 +199,19 @@ function Consumer() { }; return process; } + function makePtyProxy(token){ + var pty = makeStreamProxy(token); + var pid = token.pid; + pty.pid = pid; + proxyProcesses[pid] = pty; + pty.kill = function (signal) { + remote.kill(pid, signal); + }; + pty.resize = function (cols, rows) { + remote.resize(pid, cols, rows); + }; + return pty; + } function makeWatcherProxy(token) { var watcher = new EventEmitter(); @@ -249,13 +267,13 @@ function Consumer() { if (!stream) return; stream.emit("data", chunk); } - function onEnd(id) { + function onEnd(id, chunk) { var stream = proxyStreams[id]; if (!stream) return; // TODO: not delete proxy if close is going to be called later. // but somehow do delete proxy if close won't be called later. delete proxyStreams[id]; - stream.emit("end"); + stream.emit("end", chunk); } function onClose(id) { var stream = proxyStreams[id]; @@ -361,6 +379,9 @@ function Consumer() { if (meta.process) { meta.process = makeProcessProxy(meta.process); } + if (meta.pty) { + meta.pty = makePtyProxy(meta.pty); + } if (meta.watcher) { meta.watcher = makeWatcherProxy(meta.watcher); } @@ -393,7 +414,6 @@ inherits(Consumer, Agent); // Emit the wrapped API, not the raw one Consumer.prototype._emitConnect = function () { - this.vfs.env = this.remoteEnv; this.emit("connect", this.vfs); }; diff --git a/package.json b/package.json index 384626b..3bb77d2 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ ], "name": "vfs-socket", "description": "A vfs helper library that communicates through a serialized socket", - "version": "0.3.12", + "version": "0.3.13", "repository": { "type": "git", "url": "git://github.com/c9/vfs-socket.git" From 0829ad714d128f3603d6b0a000e5d04e67e60188 Mon Sep 17 00:00:00 2001 From: Ruben Daniels <ruben@c9.io> Date: Tue, 21 May 2013 18:33:59 +0200 Subject: [PATCH 02/12] * including the worker --- worker.js | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/worker.js b/worker.js index 04811d2..8a4895a 100644 --- a/worker.js +++ b/worker.js @@ -30,6 +30,9 @@ function Worker(vfs) { // Endpoints for processes at meta.process kill: kill, + // Endpoints for processes at meta.pty + resize: resize, + // Endpoint for watchers at meta.watcher close: closeWatcher, @@ -59,6 +62,7 @@ function Worker(vfs) { watch: route("watch"), connect: route("connect"), spawn: route("spawn"), + pty: route("pty"), execFile: route("execFile"), extend: route("extend"), unextend: route("unextend"), @@ -162,9 +166,9 @@ function Worker(vfs) { stream.pause && stream.pause(); } }); - stream.on("end", function () { + stream.on("end", function (chunk) { delete streams[id]; - remote.onEnd(id); + remote.onEnd(id, chunk); nextStreamID = id; }); } @@ -179,7 +183,7 @@ function Worker(vfs) { return token; } - function storeProcess(process) { + function storeProcess(process, onlyPid) { var pid = process.pid; processes[pid] = process; process.on("exit", function (code, signal) { @@ -188,15 +192,20 @@ function Worker(vfs) { }); process.on("close", function () { delete processes[pid]; - delete streams[process.stdout.id]; - delete streams[process.stderr.id]; - delete streams[process.stdin.id]; + if (!onlyPid) { + delete streams[process.stdout.id]; + delete streams[process.stderr.id]; + delete streams[process.stdin.id]; + } remote.onProcessClose(pid); }); process.kill = function(code) { killtree(pid, code); }; + + if (onlyPid) + return pid; var token = {pid: pid}; token.stdin = storeStream(process.stdin); @@ -204,6 +213,14 @@ function Worker(vfs) { token.stderr = storeStream(process.stderr); return token; } + + function storePty(pty) { + var pid = storeProcess(pty, true); + var token = storeStream(pty); + token.pid = pid; + + return token; + } function killtree(pid, code) { childrenOfPid(pid, function(err, pidlist){ @@ -293,6 +310,15 @@ function Worker(vfs) { process.kill(code); } + function resize(pid, cols, rows) { + var process = processes[pid]; + if (!process) return; + + // Resize can throw + try { process.resize(cols, rows); } + catch(e) {}; + } + function closeWatcher(id) { var watcher = watchers[id]; if (!watcher) return; @@ -324,13 +350,13 @@ function Worker(vfs) { if (!stream) return; stream.emit("data", chunk); } - function onEnd(id) { + function onEnd(id, chunk) { var stream = proxyStreams[id]; if (!stream) return; // TODO: not delete proxy if close is going to be called later. // but somehow do delete proxy if close won't be called later. delete proxyStreams[id]; - stream.emit("end"); + stream.emit("end", chunk); } function onClose(id) { var stream = proxyStreams[id]; @@ -361,6 +387,7 @@ function Worker(vfs) { switch (key) { case "stream": token.stream = storeStream(meta.stream); break; case "process": token.process = storeProcess(meta.process); break; + case "pty": token.pty = storePty(meta.pty); break; case "watcher": token.watcher = storeWatcher(meta.watcher); break; case "api": token.api = storeApi(meta.api); break; default: token[key] = meta[key]; break; From 0f62efc560b9558881dd835cf1a997f54ec1ca4a Mon Sep 17 00:00:00 2001 From: Ruben Daniels <ruben@c9.io> Date: Tue, 21 May 2013 18:38:23 +0200 Subject: [PATCH 03/12] * Reverted accidental change --- consumer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/consumer.js b/consumer.js index 0c0e984..55dc12c 100644 --- a/consumer.js +++ b/consumer.js @@ -414,6 +414,7 @@ inherits(Consumer, Agent); // Emit the wrapped API, not the raw one Consumer.prototype._emitConnect = function () { + this.vfs.env = this.remoteEnv; this.emit("connect", this.vfs); }; From 30ce5f320705ae84b9a8517b9bb975f47fbb1b0c Mon Sep 17 00:00:00 2001 From: Ruben Daniels <ruben@c9.io> Date: Fri, 24 May 2013 22:08:35 +0000 Subject: [PATCH 04/12] Basic deploy workflow --- events-amd.js | 1 + 1 file changed, 1 insertion(+) diff --git a/events-amd.js b/events-amd.js index ca8b051..4b787e1 100644 --- a/events-amd.js +++ b/events-amd.js @@ -261,6 +261,7 @@ EventEmitter.prototype.removeListener = function(type, listener) { return this; }; +EventEmitter.prototype.off = EventEmitter.prototype.removeListener; /** * Removes all listeners, or those of the specified event. From 5555e88847ea09d1132009cade9eb36da2aaa0ce Mon Sep 17 00:00:00 2001 From: nightwing <amirjanyan@gmail.com> Date: Fri, 14 Jun 2013 21:07:20 +0400 Subject: [PATCH 05/12] do not crash chrome intentionally --- consumer.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/consumer.js b/consumer.js index 55dc12c..c09a761 100644 --- a/consumer.js +++ b/consumer.js @@ -127,8 +127,9 @@ function Consumer() { }); this.on("error", function(err){ - this.emit("error", err); - }) + // just adding an empty listener so that events-amd doesn't throw + console.error(err); + }); var nextStreamID = 1; function storeStream(stream) { From 1fd048d480d95891f7c633428bb86eabbe3aa140 Mon Sep 17 00:00:00 2001 From: Ruben Daniels <ruben@c9.io> Date: Wed, 26 Jun 2013 16:49:48 +0000 Subject: [PATCH 06/12] * Nak should run out of process * Why is findinfiles in the Find menu disabled when ace is not opened? * Watchers shouldn't have multiple watchers for the same path * Watchers should ignore .c9config --- consumer.js | 3 +-- worker.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/consumer.js b/consumer.js index c09a761..4dcf5dd 100644 --- a/consumer.js +++ b/consumer.js @@ -133,6 +133,7 @@ function Consumer() { var nextStreamID = 1; function storeStream(stream) { + nextStreamID = nextStreamID++ % 10000; while (streams.hasOwnProperty(nextStreamID)) { nextStreamID++; } var id = nextStreamID; streams[id] = stream; @@ -146,13 +147,11 @@ function Consumer() { stream.on("end", function (chunk) { delete streams[id]; remote.onEnd(id, chunk); - nextStreamID = id; }); } stream.on("close", function () { delete streams[id]; remote.onClose(id); - nextStreamID = id; }); var token = {id: id}; if (stream.hasOwnProperty("readable")) token.readable = stream.readable; diff --git a/worker.js b/worker.js index 8a4895a..9ff1bb3 100644 --- a/worker.js +++ b/worker.js @@ -156,6 +156,7 @@ function Worker(vfs) { var nextStreamID = 1; function storeStream(stream) { + nextStreamID = nextStreamID++ % 10000; while (streams.hasOwnProperty(nextStreamID)) { nextStreamID++; } var id = nextStreamID; streams[id] = stream; @@ -169,13 +170,11 @@ function Worker(vfs) { stream.on("end", function (chunk) { delete streams[id]; remote.onEnd(id, chunk); - nextStreamID = id; }); } stream.on("close", function () { delete streams[id]; remote.onClose(id); - nextStreamID = id; }); var token = {id: id}; if (stream.hasOwnProperty("readable")) token.readable = stream.readable; From 9192ac6ddc499cf4e1df33b86b5b7baca52d9ab1 Mon Sep 17 00:00:00 2001 From: Ruben Daniels <ruben@c9.io> Date: Thu, 27 Jun 2013 08:56:43 +0000 Subject: [PATCH 07/12] * Improved VFS fix * Files now open in changed state? --- consumer.js | 2 +- worker.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/consumer.js b/consumer.js index 4dcf5dd..2493e24 100644 --- a/consumer.js +++ b/consumer.js @@ -134,7 +134,7 @@ function Consumer() { var nextStreamID = 1; function storeStream(stream) { nextStreamID = nextStreamID++ % 10000; - while (streams.hasOwnProperty(nextStreamID)) { nextStreamID++; } + while (streams.hasOwnProperty(nextStreamID)) { nextStreamID++ % 10000; } var id = nextStreamID; streams[id] = stream; stream.id = id; diff --git a/worker.js b/worker.js index 9ff1bb3..0fbe329 100644 --- a/worker.js +++ b/worker.js @@ -157,7 +157,7 @@ function Worker(vfs) { var nextStreamID = 1; function storeStream(stream) { nextStreamID = nextStreamID++ % 10000; - while (streams.hasOwnProperty(nextStreamID)) { nextStreamID++; } + while (streams.hasOwnProperty(nextStreamID)) { nextStreamID++ % 10000; } var id = nextStreamID; streams[id] = stream; stream.id = id; From f213f3e13b1e2dc8d77af6d931631a4993e6a12e Mon Sep 17 00:00:00 2001 From: Ruben Daniels <ruben@c9.io> Date: Tue, 2 Jul 2013 11:09:58 +0000 Subject: [PATCH 08/12] Merged from master while working on metadata --- consumer.js | 1 + worker.js | 1 + 2 files changed, 2 insertions(+) diff --git a/consumer.js b/consumer.js index 2493e24..f4d129f 100644 --- a/consumer.js +++ b/consumer.js @@ -62,6 +62,7 @@ function Consumer() { ping: ping, // Send a simple ping request to the worker resolve: route("resolve"), stat: route("stat"), + metadata: route("metadata"), readfile: route("readfile"), readdir: route("readdir"), mkfile: route("mkfile"), diff --git a/worker.js b/worker.js index 0fbe329..b2e62a5 100644 --- a/worker.js +++ b/worker.js @@ -50,6 +50,7 @@ function Worker(vfs) { // Route other calls to the local vfs instance resolve: route("resolve"), stat: route("stat"), + metadata: route("metadata"), readfile: route("readfile"), readdir: route("readdir"), mkfile: route("mkfile"), From a07377293942ef2572c36c43016cb51818d821b0 Mon Sep 17 00:00:00 2001 From: Ruben Daniels <ruben@c9.io> Date: Wed, 3 Jul 2013 18:29:47 +0000 Subject: [PATCH 09/12] working on vfs improvements --- consumer.js | 4 ++-- worker.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/consumer.js b/consumer.js index f4d129f..fbee748 100644 --- a/consumer.js +++ b/consumer.js @@ -309,7 +309,7 @@ function Consumer() { if (!stream) return; stream.destroy(); delete streams[id]; - nextStreamID = id; + // nextStreamID = id; } function pause(id) { var stream = streams[id]; @@ -327,7 +327,7 @@ function Consumer() { delete streams[id]; if (chunk) stream.end(chunk); else stream.end(); - nextStreamID = id; + // nextStreamID = id; } function on(name, handler, callback) { diff --git a/worker.js b/worker.js index b2e62a5..6e3938a 100644 --- a/worker.js +++ b/worker.js @@ -293,7 +293,7 @@ function Worker(vfs) { if (!stream) return; delete streams[id]; stream.destroy(); - nextStreamID = id; + // nextStreamID = id; } function end(id, chunk) { var stream = streams[id]; @@ -301,7 +301,7 @@ function Worker(vfs) { delete streams[id]; if (chunk) stream.end(chunk); else stream.end(); - nextStreamID = id; + // nextStreamID = id; } function kill(pid, code) { From f4dcedae04a08412832cf0d38278b52705861848 Mon Sep 17 00:00:00 2001 From: Ruben Daniels <ruben@c9.io> Date: Mon, 8 Jul 2013 09:16:04 +0000 Subject: [PATCH 10/12] Fix for processes not being terminated during disconnect --- worker.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/worker.js b/worker.js index 6e3938a..3420230 100644 --- a/worker.js +++ b/worker.js @@ -112,16 +112,18 @@ function Worker(vfs) { err = new Error("EDISCONNECT: vfs socket disconnected"); err.code = "EDISCONNECT"; } - Object.keys(streams).forEach(function (id) { - var stream = streams[id]; - stream.emit("close", err); - }); - Object.keys(proxyStreams).forEach(onClose); Object.keys(processes).forEach(function (pid) { var process = processes[pid]; + console.log("PROCESS", process) process.kill(); delete processes[pid]; }); + Object.keys(streams).forEach(function (id) { + var stream = streams[id]; + console.log("STREAM", stream) + stream.emit("close", err); + }); + Object.keys(proxyStreams).forEach(onClose); Object.keys(watchers).forEach(function (id) { var watcher = watchers[id]; delete watchers[id]; From cf68f34066bb8d16f808d9b7172b7662f235d1ae Mon Sep 17 00:00:00 2001 From: Ruben Daniels <ruben@c9.io> Date: Mon, 8 Jul 2013 09:16:40 +0000 Subject: [PATCH 11/12] added the fix to consumer as well --- consumer.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/consumer.js b/consumer.js index fbee748..58cca19 100644 --- a/consumer.js +++ b/consumer.js @@ -105,16 +105,16 @@ function Consumer() { err = new Error("EDISCONNECT: vfs socket disconnected"); err.code = "EDISCONNECT"; } - Object.keys(streams).forEach(function (id) { - var stream = streams[id]; - stream.emit("close"); - }); - Object.keys(proxyStreams).forEach(onClose); Object.keys(proxyProcesses).forEach(function (pid) { var proxyProcess = proxyProcesses[pid]; delete proxyProcesses[pid]; proxyProcess.emit("exit", 1); }); + Object.keys(streams).forEach(function (id) { + var stream = streams[id]; + stream.emit("close"); + }); + Object.keys(proxyStreams).forEach(onClose); Object.keys(proxyWatchers).forEach(function (id) { var proxyWatcher = proxyWatchers[id]; delete proxyWatchers[id]; From e1183d2f073e05f95c060dcb6241ad6a76e46637 Mon Sep 17 00:00:00 2001 From: Ruben Daniels <ruben@c9.io> Date: Mon, 8 Jul 2013 09:31:23 +0000 Subject: [PATCH 12/12] Removed console.log and commented out code --- consumer.js | 2 -- worker.js | 4 ---- 2 files changed, 6 deletions(-) diff --git a/consumer.js b/consumer.js index 58cca19..fe18be3 100644 --- a/consumer.js +++ b/consumer.js @@ -309,7 +309,6 @@ function Consumer() { if (!stream) return; stream.destroy(); delete streams[id]; - // nextStreamID = id; } function pause(id) { var stream = streams[id]; @@ -327,7 +326,6 @@ function Consumer() { delete streams[id]; if (chunk) stream.end(chunk); else stream.end(); - // nextStreamID = id; } function on(name, handler, callback) { diff --git a/worker.js b/worker.js index 3420230..c37adb0 100644 --- a/worker.js +++ b/worker.js @@ -114,13 +114,11 @@ function Worker(vfs) { } Object.keys(processes).forEach(function (pid) { var process = processes[pid]; - console.log("PROCESS", process) process.kill(); delete processes[pid]; }); Object.keys(streams).forEach(function (id) { var stream = streams[id]; - console.log("STREAM", stream) stream.emit("close", err); }); Object.keys(proxyStreams).forEach(onClose); @@ -295,7 +293,6 @@ function Worker(vfs) { if (!stream) return; delete streams[id]; stream.destroy(); - // nextStreamID = id; } function end(id, chunk) { var stream = streams[id]; @@ -303,7 +300,6 @@ function Worker(vfs) { delete streams[id]; if (chunk) stream.end(chunk); else stream.end(); - // nextStreamID = id; } function kill(pid, code) {