Skip to content

fix: allow the context on env load to be canceled [IDE-1791]#564

Open
rrama wants to merge 4 commits intomainfrom
fix/IDE-1791_env-loading-context
Open

fix: allow the context on env load to be canceled [IDE-1791]#564
rrama wants to merge 4 commits intomainfrom
fix/IDE-1791_env-loading-context

Conversation

@rrama
Copy link
Copy Markdown
Contributor

@rrama rrama commented Mar 5, 2026

Plus other nice to have options can be passed.
Needed for snyk/snyk-ls#1173

Plus other nice to have options can be passed.
@snyk-io
Copy link
Copy Markdown

snyk-io bot commented Mar 5, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@rrama rrama changed the title fix: allow the context on env load to be canceled fix: allow the context on env load to be canceled [IDE-1791] Mar 5, 2026
@snyk-io
Copy link
Copy Markdown

snyk-io bot commented Mar 5, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@rrama rrama marked this pull request as ready for review March 5, 2026 11:11
@rrama rrama requested review from a team as code owners March 5, 2026 11:11
logger *zerolog.Logger
}

type LoadConfiguredEnvironmentOptions func(opts *loadConfiguredEnvironmentOptions)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, don't we need to export the loadConfiguredEnvironmentOptions struct? I wonder how external processes should work with the pointer to the struct?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, actually we don't need either exported, we only need the pre-defined WithBlah functions exported, as that is all the external callers should interact with.

Although in theory someone may want to create a slice of the WithBlah functions, but if someone does want to do something that peculiar, they can come it and change it to be exported.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made it unexported.

@bastiandoetsch
Copy link
Copy Markdown
Contributor

/review

}
}

func WithCustomConfigFiles(customConfigFiles []string, workingDirectory string) LoadConfiguredEnvironmentOptions {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For ease of use:

  • shouldn't the custom config files be just absolute paths?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that not just more effort for the caller? They would need to join all the .snyk.env, .envrc, etc. with the working dir path before calling.
Hmm, as a best of both, I could rename this one to WithRelativeCustomConfigFiles and then do a second function that is just for absolute config files.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made it so you have to pass absolute paths, but I added a util function that converts relative paths to absolute paths to make life easier for the callers.

@snyk-pr-review-bot

This comment has been minimized.

// The Bash env PATH is appended to the existing PATH (as a fallback), any other new PATH read is prepended (preferential).
func LoadConfiguredEnvironmentWithOptions(opts ...LoadConfiguredEnvironmentOptions) {
options := loadConfiguredEnvironmentOptions{
ctx: context.Background(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess, this should be a context with timeout of e.g. 5s

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getEnvFromShell already puts a 5 second timeout on the context. But we could shift the timeout up to encompass the entirety of the loading env if that's better?

Copy link
Copy Markdown
Contributor Author

@rrama rrama Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried moving the timeout up, but then you have to decide if you want it before or after getting the mutex, so I decided in the end to leave it as it currently is with only the timeout in getEnvFromShell. A caller can always specify a timeout on the context they pass.

Now requires absolute paths. But I also added a util function to make paths absolute.
Added an overall timeout for the entire `LoadConfiguredEnvironmentWithOptions` function.
@snyk-pr-review-bot

This comment has been minimized.

@snyk-pr-review-bot

This comment has been minimized.

It was clashing with the mutex locking. The caller can just provide a timeout on their context.
Make logging more accurate.
@snyk-pr-review-bot
Copy link
Copy Markdown

PR Reviewer Guide 🔍

🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Inefficient Lock Acquisition 🟠 [major]

The function LoadConfiguredEnvironmentWithOptions acquires a package-level mutex mu before checking if the provided context options.ctx is already canceled. Since sync.Mutex.Lock() is not context-aware, a caller passing a canceled context will still block until any ongoing environment loading (which can take up to 10 seconds due to shell execution timeouts) finishes and releases the lock. This defeats the primary purpose of the PR, which is to allow the environment loading process to be responsive to cancellation.

mu.Lock()
defer func() {
	mu.Unlock()
Redundant Logger Wrapping 🟡 [minor]

In LoadConfiguredEnvironmentWithOptions, a new logger is created with a "method" field. However, getEnvFromShell is then called with options.logger (the original logger) instead of the decorated logger. This results in getEnvFromShell's logs missing the "method" context established at the start of the calling function, leading to inconsistent log metadata across the execution flow.

bashOutput := getEnvFromShell(options.ctx, options.logger, "bash")
📚 Repository Context Analyzed

This review considered 15 relevant code sections from 15 files (average relevance: 1.03)

@rrama rrama added the 🚧 Blocked PR is blocked waiting for something else first label Mar 12, 2026
@rrama
Copy link
Copy Markdown
Contributor Author

rrama commented Mar 12, 2026

The LS PR is blocked, I do want to mark the other function as deprecated, so I will wait to merge this until then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🚧 Blocked PR is blocked waiting for something else first

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants