-
Notifications
You must be signed in to change notification settings - Fork 37.2k
fix pty output make main process oom #285419
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
base: main
Are you sure you want to change the base?
fix pty output make main process oom #285419
Conversation
📬 CODENOTIFYThe following users are being notified based on files changed in this PR: @deepak1556Matched files:
|
|
@microsoft-github-policy-service agree |
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.
Pull request overview
This PR fixes a memory leak (OOM) in the main Electron process caused by unbounded buffering of PTY process output. The local PTY process communicates directly with the renderer process via MessagePort, but the main process was also buffering all onProcessData events even though they were never consumed, leading to memory exhaustion.
Key Changes:
- Added a
skipoption toProxyChannel.fromServiceto selectively exclude events from registration - Applied the skip option to exclude
onProcessDataevents from the main process PTY service channel
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/vs/base/parts/ipc/common/ipc.ts |
Added skip option to ICreateServiceChannelOptions interface to allow selective event registration filtering |
src/vs/code/electron-main/app.ts |
Applied skip option to exclude onProcessData from the PTY host channel registration in main process |
bd57057 to
e2bb946
Compare
e2bb946 to
4eaa235
Compare
Tyriar
left a comment
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.
lgtm thanks!
FYI @joaomoreno @alexdima if you have thoughts on ipc/ parts
| * If return true for a event key, we add the handler to event | ||
| * until the first listener is registered. | ||
| */ | ||
| isLazyEvent?: (key: string) => boolean; |
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 am reading this comment and fail to understand what actually happens when I use this option. If I understand correctly, a "lazy" event will not buffer any data until a first listener is added. But then I would update this comment to actually explain this better. And should be called differently?
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.
Yes. I have updated the comment, please help review again .
| // Terminal | ||
| const ptyHostChannel = ProxyChannel.fromService(accessor.get(ILocalPtyService), disposables); | ||
| const ptyHostChannel = ProxyChannel.fromService(accessor.get(ILocalPtyService), disposables, { | ||
| isLazyEvent: (key: string) => key === 'onProcessData' |
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.
Whats the rule here to decide if an event should be lazy? Does this apply to other proxy channels?
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.
Thanks for reviewing ! An event should be lazy if it is triggered automatically but may not have subscribers; otherwise, the event data will be cached in the buffer (Event.buffer), causing a memory leak. I only find that ptyHostService.onProcessData should be lazy currently.
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.
@theanarkh I think what @bpasero is likely getting at is this should get fixed generically to prevent future leaks like this in the future. onProcessData is used, but conditionally, just because an event isn't listened to shouldn't mean the data should hang around forever. Any thoughts on how we could solve this generically for all events without hardcoding this particular event or compromising performance?
Head branch was pushed to by a user without write access
4eaa235 to
3415bc2
Compare
Fixes #234393
The local pty process communicates directly with the render process, but the main process save the output of pty process to buffer and there is no consumer.
Running
in the terminal and take a JS heap snapshot of main process.
take JS heap snapshot again after some time.