Skip to content

Commit ce35f96

Browse files
committed
shutdown typing installer if parent process is exited
1 parent 758d8de commit ce35f96

3 files changed

Lines changed: 54 additions & 14 deletions

File tree

src/server/server.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace ts.server {
1212
interface NodeChildProcess {
1313
send(message: any, sendHandle?: any): void;
1414
on(message: "message", f: (m: any) => void): void;
15+
kill(): void;
1516
}
1617

1718
const childProcess: {
@@ -175,6 +176,10 @@ namespace ts.server {
175176

176177
this.installer = childProcess.fork(combinePaths(__dirname, "typingsInstaller.js"));
177178
this.installer.on("message", m => this.handleMessage(m));
179+
process.on("exit", () => {
180+
this.installer.kill();
181+
})
182+
178183
}
179184

180185
onProjectClosed(p: Project): void {

src/server/typingsInstaller/nodeTypingsInstaller.ts

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ namespace ts.server.typingsInstaller {
5252

5353
constructor(log?: Log) {
5454
super(getGlobalCacheLocation(), toPath("typingSafeList.json", __dirname, createGetCanonicalFileName(sys.useCaseSensitiveFileNames)), log);
55+
if (this.log.isEnabled()) {
56+
this.log.writeLine(`Process id: ${process.pid}`);
57+
}
5558
const { exec, execSync } = require("child_process");
5659
this.execSync = execSync;
5760
this.exec = exec;
@@ -84,20 +87,34 @@ namespace ts.server.typingsInstaller {
8487

8588
protected isPackageInstalled(packageName: string) {
8689
try {
87-
this.execSync(`npm list --global --depth=1 ${packageName}`, { stdio: "ignore" });
90+
const output = this.execSync(`npm list --global --depth=1 ${packageName}`, { stdio: "pipe" }).toString();
91+
if (this.log.isEnabled()) {
92+
this.log.writeLine(`IsPackageInstalled::stdout '${output}'`);
93+
}
8894
return true;
8995
}
9096
catch (e) {
97+
if (this.log.isEnabled()) {
98+
this.log.writeLine(`IsPackageInstalled::err::stdout '${e.stdout && e.stdout.toString()}'`);
99+
this.log.writeLine(`IsPackageInstalled::err::stderr '${e.stdout && e.stderr.toString()}'`);
100+
}
91101
return false;
92102
}
93103
}
94104

95105
protected installPackage(packageName: string) {
96106
try {
97-
this.execSync(`npm install --global ${packageName}`, { stdio: "ignore" });
107+
const output = this.execSync(`npm install --global ${packageName}`, { stdio: "pipe" }).toString();
108+
if (this.log.isEnabled()) {
109+
this.log.writeLine(`installPackage::stdout '${output}'`);
110+
}
98111
return true;
99112
}
100113
catch (e) {
114+
if (this.log.isEnabled()) {
115+
this.log.writeLine(`installPackage::err::stdout '${e.stdout && e.stdout.toString()}'`);
116+
this.log.writeLine(`installPackage::err::stderr '${e.stdout && e.stderr.toString()}'`);
117+
}
101118
return false;
102119
}
103120
}
@@ -107,6 +124,9 @@ namespace ts.server.typingsInstaller {
107124
this.log.writeLine(`Sending response: ${JSON.stringify(response)}`)
108125
}
109126
process.send(response);
127+
if (this.log.isEnabled()) {
128+
this.log.writeLine(`Response has been sent.`)
129+
}
110130
}
111131

112132
protected runTsd(cachePath: string, typingsToInstall: string[], postInstallAction: (installedTypings: string[]) => void): void {
@@ -139,11 +159,15 @@ namespace ts.server.typingsInstaller {
139159
}
140160

141161
const log = new FileLog(process.env.TI_LOG_FILE);
142-
process.on("uncaughtException", (e: Error) => {
143-
if (log.isEnabled()) {
162+
if (log.isEnabled()) {
163+
process.on("uncaughtException", (e: Error) => {
144164
log.writeLine(`Unhandled exception: ${e} at ${e.stack}`);
145-
}
146-
})
165+
});
166+
process.on("disconnect", () => {
167+
log.writeLine(`Parent process has exited, shutting down...`);
168+
process.exit(0);
169+
});
170+
}
147171
const installer = new NodeTypingsInstaller(log);
148172
installer.init();
149173
}

src/server/typingsInstaller/typingsInstaller.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ namespace ts.server.typingsInstaller {
7272
this.closeWatchers(req.projectName);
7373
}
7474

75-
private closeWatchers(projectName: string): boolean {
75+
private closeWatchers(projectName: string): void {
7676
if (this.log.isEnabled()) {
7777
this.log.writeLine(`Closing file watchers for project '${projectName}'`);
7878
}
@@ -82,7 +82,7 @@ namespace ts.server.typingsInstaller {
8282
this.log.writeLine(`No watchers are registered for project '${projectName}'`);
8383
}
8484

85-
return false;
85+
return;
8686
}
8787
for (const w of watchers) {
8888
w.close();
@@ -93,8 +93,6 @@ namespace ts.server.typingsInstaller {
9393
if (this.log.isEnabled()) {
9494
this.log.writeLine(`Closing file watchers for project '${projectName}' - done.`);
9595
}
96-
97-
return true;
9896
}
9997

10098
install(req: DiscoverTypings) {
@@ -137,7 +135,14 @@ namespace ts.server.typingsInstaller {
137135
this.watchFiles(req.projectName, discoverTypingsResult.filesToWatch);
138136

139137
// install typings
140-
this.installTypings(req, req.cachePath || this.globalCachePath, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames);
138+
if (discoverTypingsResult.newTypingNames.length) {
139+
this.installTypings(req, req.cachePath || this.globalCachePath, discoverTypingsResult.cachedTypingPaths, discoverTypingsResult.newTypingNames);
140+
}
141+
else {
142+
if (this.log.isEnabled()) {
143+
this.log.writeLine(`No new typings were requested as a result of typings discovery`);
144+
}
145+
}
141146
}
142147

143148
private processCacheLocation(cacheLocation: string) {
@@ -259,17 +264,23 @@ namespace ts.server.typingsInstaller {
259264
if (!files.length) {
260265
return;
261266
}
267+
// shut down existing watchers
268+
this.closeWatchers(projectName);
269+
270+
// handler should be invoked once for the entire set of files since it will trigger full rediscovery of typings
271+
let isInvoked = false;
262272
const watchers: FileWatcher[] = [];
263273
for (const file of files) {
264274
const w = this.installTypingHost.watchFile(file, f => {
265275
if (this.log.isEnabled()) {
266-
this.log.writeLine(`FS notification for '${f}', sending 'clean' message for project '${projectName}'`);
276+
this.log.writeLine(`Got FS notification for ${f}, handler is already invoked '${isInvoked}'`);
267277
}
268-
this.closeWatchers(projectName);
269-
this.sendResponse(<InvalidateCachedTypings>{ projectName: projectName, kind: "invalidate" })
278+
this.sendResponse({ projectName: projectName, kind: "invalidate" });
279+
isInvoked = true;
270280
});
271281
watchers.push(w);
272282
}
283+
this.projectWatchers[projectName] = watchers;
273284
}
274285

275286
private createSetTypings(request: DiscoverTypings, typings: string[]): SetTypings {

0 commit comments

Comments
 (0)