-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
RUST_THREADS=1 must stay with a single thread, which the runtime doesn't #9373
Comments
It's intentional. By default the runtime doesn't put any tasks on the main thread. Using the unstable runtime API it would not be hard to construct a runtime that ran tasks only on the main thread, though you will still run into situations where, e.g. the I/O subsystem starts other threads on its own. The code for initializing the runtime is https://github.com/mozilla/rust/blob/master/src/libstd/rt/mod.rs#L234 With some tweaking this could be adjusted to only put tasks on the main thread: the The way to invoke the runtime API directly is by using the |
I didn't understand this was intentional when I wrote up this ticket. (From #rust irc I got the impression that RUST_THREADS=1 was supposed to keep threads down to 1.) Nonetheless, for my use case where I can't really tolerate more than one thread (using fork(2) calls to get inexpensive + comprehensive transaction semantics for rusti), it would be really great to have a global policy flag somewhere in Rust that is easily settable, that can be easily checked by all programmers, and that can be expected to be honored everywhere. What is desired is some easy way to tell the runtime (and any implementors implementing new, additional features), "Yeah, really, don't spawn any threads, thank you very much; if a background thread is holding a mutex for malloc, this will really hose us if we happen to fork at that moment." Under this one-thread regime, multiple coroutines are okay, but they should be cooperatively scheduled on the single main thread of the application. Does this seem viable? It also seems desirable if you are writing embedded systems that do not offer OS level threads. |
I tried using start_on_main_thread, and Rust still spawns an additional thread. (RUST_THREADS=1 is set).
|
This isn't fixable, because threads are needed to make large writes non-blocking. See #9568 for a feasible but unlikely solution. |
Initial implementation `result_large_err` This is a shot at rust-lang#6560, rust-lang#4652, and rust-lang#3884. The lint checks for `Result` being returned from functions/methods where the `Err` variant is larger than a configurable threshold (the default of which is 128 bytes). There has been some discussion around this, which I'll try to quickly summarize: * A large `Err`-variant may force an equally large `Result` if `Err` is actually bigger than `Ok`. * There is a cost involved in large `Result`, as LLVM may choose to `memcpy` them around above a certain size. * We usually expect the `Err` variant to be seldomly used, but pay the cost every time. * `Result` returned from library code has a high chance of bubbling up the call stack, getting stuffed into `MyLibError { IoError(std::io::Error), ParseError(parselib::Error), ...}`, exacerbating the problem. This PR deliberately does not take into account comparing the `Ok` to the `Err` variant (e.g. a ratio, or one being larger than the other). Rather we choose an absolute threshold for `Err`'s size, above which we warn. The reason for this is that `Err`s probably get `map_err`'ed further up the call stack, and we can't draw conclusions from the ratio at the point where the `Result` is returned. A relative threshold would also be less predictable, while not accounting for the cost of LLVM being forced to generate less efficient code if the `Err`-variant is _large_ in absolute terms. We lint private functions as well as public functions, as the perf-cost applies to in-crate code as well. In order to account for type-parameters, I conjured up `fn approx_ty_size`. The function relies on `LateContext::layout_of` to compute the actual size, and in case of failure (e.g. due to generics) tries to come up with an "at least size". In the latter case, the size of obviously wrong, but the inspected size certainly can't be smaller than that. Please give the approach a heavy dose of review, as I'm not actually familiar with the type-system at all (read: I have no idea what I'm doing). The approach does, however flimsy it is, allow us to successfully lint situations like ```rust pub union UnionError<T: Copy> { _maybe: T, _or_perhaps_even: (T, [u8; 512]), } // We know `UnionError<T>` will be at least 512 bytes, no matter what `T` is pub fn param_large_union<T: Copy>() -> Result<(), UnionError<T>> { Ok(()) } ``` I've given some refactoring to `functions/result_unit_err.rs` to re-use some bits. This is also the groundwork for rust-lang#6409 The default threshold is 128 because of rust-lang/rust-clippy#4652 (comment) `lintcheck` does not trigger this lint for a threshold of 128. It does warn for 64, though. The suggestion currently is the following, which is just a placeholder for discussion to be had. I did have the computed size in a `span_label`. However, that might cause both ui-tests here and lints elsewhere to become flaky wrt to their output (as the size is platform dependent). ``` error: the `Err`-variant returned via this `Result` is very large --> $DIR/result_large_err.rs:36:34 | LL | pub fn param_large_error<R>() -> Result<(), (u128, R, FullyDefinedLargeError)> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The `Err` variant is unusually large, at least 128 bytes ``` changelog: Add [`result_large_err`] lint
Use `approx_ty_size` for `large_enum_variant` This builds upon rust-lang#9373 to use the approximate size of each variant for `large_enum_variant`. This allows us to lint in situations where an `enum` contains generics but is still guaranteed to have a large variant on an at-least basis, e.g. with `(T, [u8; 512])`. * I've changed the wording from "is ... bytes" to "contains at least" because * the size is now an approximate lower bound (e.g. `512` in the example above). The actual size is larger due to `T`, including due to `T`'s memory layout. * the discriminant is not taken into account in the message. This comes up with variants like `A(T)`, which are "is at least 0 bytes" otherwise, which may be misleading. * If the second-largest variant has no fields, there is a special case "carries no data" instead of "is at least 0 bytes". * A variant like `A(T)` is "at least 0 bytes", which is technically true, yet we don't distinguish between "indeterminate" and truly "ZST". * The generics-tests that were there before now lint while they didn't lint before. AFAICS this is correct. I guess the above is correct-ish. However, I use the `SubstsRef` that I got via `cx.tcx.type_of(item.def_id)` to solve for generics in the variants. Is this even applicable, since we start from an - [ ] `ItemKind`? changelog: none
Add size-parameter to unecessary_box_returns Fixes rust-lang#10641 This adds a configuration-knob to the `unecessary_box_returns`-lint which allows _not_ linting a `fn() -> Box<T>` if `T` is "large". The default byte size above which we no longer lint is 128 bytes (due to rust-lang/rust-clippy#4652 (comment), also used in rust-lang#9373). The overall rational is given in rust-lang#10641. --- changelog: Enhancement: [`unnecessary_box_returns`]: Added new lint configuration `unnecessary-box-size` to set the maximum size of `T` in `Box<T>` to be linted [rust-lang#10651](rust-lang/rust-clippy#10651) <!-- changelog_checked -->
rustc 0.8-pre (570431f 2013-09-19 15:56:04 -0700)
RUST_THREADS=1 must not allow the rust runtime to start a second thread, which it does now. This is really bad.
Background: If I wish to fork(2) and use the resulting image, only the thread that calls fork(2) gets duplicated. If any other thread has locked a mutex (say for printf, or malloc) and was in the middle of a critical section, then those locks remain locked, the other threads vanish, and my new child process is hosed.
From the rust-dev thread on rusti - the - repl renovation: (20 sept 2013):
I'm trying some sanity checks. This one had a curious result. I did
$ export RUST_THREADS=1
and then started rusti under gdb. Expected: only one thread going. Observed: I have two threads going instead.
(This is troublesome, because fork will never work if Rust doesn't honor the request of RUST_THREADS=1; you can't mix threads and fork; explanation: http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them )
Q: Is there a way to really just get one thread in the rust runtime? Best case, I'm hoping the two threads observed is just a bug that can be fixed.
Jason
From: Alex Crichton alex@crichton.co
Date: Fri, Sep 20, 2013 at 4:24 PM
Subject: Re: [rust-dev] rusti - the - repl renovation
To: "Jason E. Aten" j.e.aten@gmail.com
The text was updated successfully, but these errors were encountered: