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

rustc: Try to contain prepends to PATH #34083

Merged
merged 1 commit into from
Jun 8, 2016
Merged

Conversation

alexcrichton
Copy link
Member

This commit attempts to bring our prepends to PATH on Windows when loading
plugins because we've been seeing quite a few issues with failing to spawn a
process on Windows, the leading theory of which is that PATH is too large as a
result of this. Currently this is mostly a stab in the dark as it's not
confirmed to actually fix the problem, but it's probably not a bad change to
have anyway!

cc #33844
Closes #17360

@rust-highfive
Copy link
Collaborator

r? @nrc

(rust_highfive has picked a reviewer for you, use r? to override)

@alexcrichton
Copy link
Member Author

cc @vadimcn, @retep998

@xen0n
Copy link
Contributor

xen0n commented Jun 5, 2016

Would some kind of regression test be appreciated? I mean something like a crate with 1500 or so very simple doctests, which shouldn't take a very long time to execute even on Windows, and for which the pass condition is no spawn errors being thrown. Using some probability theory we could choose the exact number of dummy cases to give us any degree of confidence of such race conditions happening for a certain number of times, but I think 2000 at most would be enough.

@alexcrichton
Copy link
Member Author

Perhaps yeah! I don't have the ability to create a test right now and verify that it actually fails

let mut new_path = sess.host_filesearch(PathKind::All)
.get_dylib_search_paths();
new_path.extend(env::split_paths(&_old_path));
new_path.retain(|p| !old_paths.contains(p));
Copy link
Contributor

Choose a reason for hiding this comment

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

This changes the semantics! Before we're ensuring that the intended paths are always searched first, but now one only have to guess the path in advance to prevent it from being prepended. This might have security consequences given Windows's reputation on dynamic library searching, and IMO it'll be better to delete the path from old_path instead.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah I don't think it actually matters, but the hash set is probably overkill here anyway.

@xen0n
Copy link
Contributor

xen0n commented Jun 5, 2016

@alexcrichton Okay, I'll attempt to do this in a separate PR and post the results later (tomorrow maybe). Seems a rustdoc test is appropriate. I think the testcase only have to make the unpatched rustdoc fail like ~90% of the time?

EDIT: no this perhaps shouldn't count as a testcase, because race conditions are inherently difficult and sporadic things to test, and in case someone runs the test with a single core they would simply be wasting their time. I would paste my results as a gist later maybe.

This commit attempts to bring our prepends to PATH on Windows when loading
plugins because we've been seeing quite a few issues with failing to spawn a
process on Windows, the leading theory of which is that PATH is too large as a
result of this. Currently this is mostly a stab in the dark as it's not
confirmed to actually fix the problem, but it's probably not a bad change to
have anyway!

cc rust-lang#33844
Closes rust-lang#17360
let mut new_path = sess.host_filesearch(PathKind::All)
.get_dylib_search_paths();
new_path.extend(env::split_paths(&_old_path));
for path in env::split_paths(&old_path) {
if !new_path.contains(&path) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Although this makes the for loop O(n^2), it is fine IMO because new_path shouldn't have too many entries.

Copy link
Contributor

Choose a reason for hiding this comment

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

No, it's repeatedly adding up!

Copy link
Contributor

@xen0n xen0n Jun 5, 2016

Choose a reason for hiding this comment

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

I would do something like:

let old_path = env::split_paths(&old_path).filter(|p| !new_path.contains(p)).collect();
new_path.extend(old_path);

This collect is necessary to make sure all new_path queries are looking at its pristine state. Or make another HashSet from new_path just to be explicit and O(1), but I'd not go that far. (Consulting a constant list is also O(1) actually.)

Copy link
Member Author

Choose a reason for hiding this comment

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

No, when run concurrently everything is adding the same paths, so it doesn't add up. There's no way this is more expensive than, say, reading the source file.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fair point! Premature optimization is evil, yeah? 😈

@vadimcn
Copy link
Contributor

vadimcn commented Jun 6, 2016

LGTM (or, better than it was, at least :).

If you care about the remaining raciness: it seems to me that the list returned by the host_filesearch() is not going to change from call to call. Could we modify PATH only when the first thread enters this block and restore it when the last one leaves?

@alexcrichton
Copy link
Member Author

Hm I think host_filesearch uses -L, right? And that can change between sessions?

Regardless though this was something I didn't really want to invest much thought in, it doesn't really matter whether this is globally synchronized or has some logic like this, this is literally only exercised by rustdoc --test and nothing else (the bug). In that sense I just want some fix to land so we can stop having flaky tests on the bots.

@nrc
Copy link
Member

nrc commented Jun 7, 2016

@bors: r+

@bors
Copy link
Contributor

bors commented Jun 7, 2016

📌 Commit 1564e92 has been approved by nrc

@bors
Copy link
Contributor

bors commented Jun 8, 2016

⌛ Testing commit 1564e92 with merge 4b240fe...

bors added a commit that referenced this pull request Jun 8, 2016
rustc: Try to contain prepends to PATH

This commit attempts to bring our prepends to PATH on Windows when loading
plugins because we've been seeing quite a few issues with failing to spawn a
process on Windows, the leading theory of which is that PATH is too large as a
result of this. Currently this is mostly a stab in the dark as it's not
confirmed to actually fix the problem, but it's probably not a bad change to
have anyway!

cc #33844
Closes #17360
@bors bors merged commit 1564e92 into rust-lang:master Jun 8, 2016
@alexcrichton alexcrichton deleted the dumb-hack branch June 28, 2016 20:27
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.

rustc's munging of PATH environment is racy when run in parallel
6 participants