-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GH-815: Replace child_process
with the Process
API in the LS backend contribution
#841
Changes from all commits
b481ee7
aa32dd8
ab689d0
ad7deea
e45dfa5
580dad7
1e060a3
9558848
b5b9e0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,33 +5,38 @@ | |
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 | ||
*/ | ||
|
||
import * as stream from 'stream'; | ||
import { injectable, inject } from "inversify"; | ||
import { ProcessManager } from './process-manager'; | ||
import { ILogger, Emitter, Event } from '@theia/core/lib/common'; | ||
import * as child from 'child_process'; | ||
import * as stream from 'stream'; | ||
|
||
export interface IProcessExitEvent { | ||
code: number, | ||
signal?: string | ||
readonly code: number, | ||
readonly signal?: string | ||
} | ||
|
||
export enum ProcessType { | ||
'Raw', | ||
'Terminal' | ||
} | ||
|
||
@injectable() | ||
export abstract class Process { | ||
|
||
readonly id: number; | ||
abstract readonly type: 'Raw' | 'Terminal'; | ||
abstract pid: number; | ||
abstract output: stream.Readable; | ||
protected abstract process: child.ChildProcess | undefined; | ||
protected abstract terminal: any; | ||
protected readonly exitEmitter = new Emitter<IProcessExitEvent>(); | ||
protected readonly errorEmitter = new Emitter<Error>(); | ||
readonly exitEmitter: Emitter<IProcessExitEvent>; | ||
readonly errorEmitter: Emitter<Error>; | ||
abstract readonly pid: number; | ||
abstract readonly output: stream.Readable; | ||
protected _killed = false; | ||
|
||
constructor( | ||
@inject(ProcessManager) protected readonly processManager: ProcessManager, | ||
protected readonly logger: ILogger) { | ||
protected readonly logger: ILogger, | ||
readonly type: ProcessType) { | ||
|
||
this.exitEmitter = new Emitter<IProcessExitEvent>(); | ||
this.errorEmitter = new Emitter<Error>(); | ||
this.id = this.processManager.register(this); | ||
} | ||
|
||
|
@@ -41,34 +46,24 @@ export abstract class Process { | |
return this._killed; | ||
} | ||
|
||
set killed(killed: boolean) { | ||
/* readonly public property */ | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can this be ommited ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That is a compiler error. Having a property getter is equivalent to a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK good :) that's what I wanted |
||
get onExit(): Event<IProcessExitEvent> { | ||
return this.exitEmitter.event; | ||
|
||
} | ||
|
||
get onError(): Event<Error> { | ||
return this.errorEmitter.event; | ||
|
||
} | ||
|
||
protected emitOnExit(code: number, signal?: string) { | ||
const exitEvent = { 'code': code, 'signal': signal }; | ||
const exitEvent = { code, signal }; | ||
this.handleOnExit(exitEvent); | ||
this.exitEmitter.fire(exitEvent); | ||
} | ||
|
||
protected handleOnExit(event: IProcessExitEvent) { | ||
this._killed = true; | ||
let logMsg = `Process ${this.pid} has exited with code ${event.code}`; | ||
|
||
if (event.signal !== undefined) { | ||
logMsg += `, signal : ${event.signal}.`; | ||
} | ||
this.logger.info(logMsg); | ||
const signalSuffix = event.signal ? `, signal: ${event.signal}` : ''; | ||
this.logger.info(`Process ${this.pid} has exited with code ${event.code}${signalSuffix}.`); | ||
} | ||
|
||
protected emitOnError(err: Error) { | ||
|
@@ -80,4 +75,5 @@ export abstract class Process { | |
this._killed = true; | ||
this.logger.error(error.toString()); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when will this process be deleted from the manager? as I read the code it seems never except
onStop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing them should be managed by the ProcessManager, since we might want to keep a certain amount of history about closed processes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We decided to automatically unregister processes when they are killed until we have a different way of cleaning up terminated processes in the ProcessManager.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the process being killed in the code ?
Also I think it may be good to unregister the process after all automatically but it should be done in a on('exit' callback and registered by the processManager.
This is fine a long as the Process is not disposable. That way even if it's unregistered references to that process still exists and will receive the onDeleted event.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is killed when the connection is closed:
https://github.com/theia-ide/theia/blob/3ee55262a0d2a2758e680d1d845b81e746e86b48/packages/languages/src/node/language-server-contribution.ts#L71
during forwarding, if one connection get closed another will be closed as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the on('exit' could also be in the Process class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha ok thx my comments still apply