Skip to content
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

fix: Fixing a potential race condition and possibly memory leak in "powerShellStart" #696

Closed
wants to merge 1 commit into from
Closed

Conversation

whoisyulu
Copy link

@whoisyulu whoisyulu commented Jun 15, 2022

We've been use powerShellStart and powerShellRelease in our project to minimise the number "PowerShell" processes created by SystemInformation in order to work around #626.

However, we've noticed a couple of potential problems, when powerShellStart are called multiple times, before powerShellRelease is called.

Imagine the following scenario:

  1. function 1 calls si.powerShellStart() followed by si.system(cb) (or the promise version). It'll call si.powerShellRelease once it gets the response in the callback.
  2. function 2 makes similar calls si.powerShellStart() followed by si.osInfo(cb).

(In reality, function 1 & 2 are in two different "context" therefore have no knowledge of each other regarding when which one will make the call first, hence very tricky to synchronise them.)

There are a couple of issues here:

  1. There's a chance that the call by function 2 could end up creating a new "PowerShell" process, which is not desirable, since creating "PowerShell" processes are expensive operation. It is also unnecessary to create the second "PowerShell" process, since function 2 should be able to just reuse the same "PowerShell" created by function 1.
  2. The "PowerShell" process created by function 1 now becomes an "orphan", because _psChild is global therefore it's overwritten by the one created by function 2. The callback of function 1 may never be able to release it (hence possible memory leak), where the "PowerShell" process created by function 2 are released twice.

This commit changes powerShellStart function so that it first checks if a persisted "PowerShell" process already existed, and just reuse it if one is available.

…powerShellStart` could be called multiple times, before `powerShellRelease` is called.

Imagine the following scenario:
1. function 1 calls `si.powerShellStart()` followed by `si.system(cb)` (or the promise version). It'll call "si.powerShellRelease" once it gets the response in the callback.
2. function 2 makes similar calls `si.powerShellStart()` followed by `si.os(cb)`.

There are a couple of issues here:

1. There's a chance that the call by function 2 could end up creating a new "PowerShell" process, which is not desirable, since creating "PowerShell" processes are expensive operation. It is also unnecessary to create the second "PowerShell" process, since function 2 should be able to just "reuse" the same "PowerShell" created by function 1.
2. The "PowerShell" process created by function 1 now becomes an "orphan", because `_psChild` is global therefore it's overwritten by function 2. The callback of function 1 may never be able to release it, where the "PowerShell" process created by function 2 are released twice.

This commit changes `powerShellStart` function so that it first check if a `persisted` "PowerShell" process already existed, and just reuse it if one is available.
@whoisyulu
Copy link
Author

Hi @sebhildebrandt, would be very much appreciated if you could have a look at this as soon as possible.

@whoisyulu whoisyulu changed the title fix: Fixing a potential race condition and possibly memory leak in "powerShellStart" fix: Fixing a potential race condition and possibly memory leak in **powerShellStart** Jun 15, 2022
@whoisyulu whoisyulu changed the title fix: Fixing a potential race condition and possibly memory leak in **powerShellStart** fix: Fixing a potential race condition and possibly memory leak in "powerShellStart" Jun 15, 2022
@whoisyulu
Copy link
Author

whoisyulu commented Jun 15, 2022

hmmmm, I think this change is not correct, because any caller (function 1 or function 2 in above example) could be killing the process before both of them are finished with it.

We'll probably need a way to track if _psChild is currently in use or not, before kill it. Perhaps as you mentioned, a process pool is the way to go.

I'll close this PR for now.

@whoisyulu whoisyulu closed this Jun 15, 2022
@whoisyulu
Copy link
Author

Perhaps this https://github.com/Shopify/quilt/tree/main/packages/semaphore could help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant