Prevent initializing and shutting down SpiderMonkey from different threads #487
Conversation
Ensure SpiderMonkey shuts down cleanly These changes (along with servo/rust-mozjs#487) ensure that the JS engine is initialized on a thread which is kept alive until the end of the program, when we can safely shut down the engine. --- - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #21696 and fix #22276 - [x] There are tests for these changes
Note to self: need to update unit tests. |
To elaborate on servo/servo#24845 (comment) I think you could make with enum EngineHandles {
/// Initial state, equivalent to 0 handles, but before any handles have been created.
Initialized,
/// Count handles, start at 1, goes to 0 when all handles are dropped.
Count(u32)
} with So that the thread in script can then block on that call, and then shutdown. |
pub struct JSEngine { | ||
/// The count of alive handles derived from this initialized instance. | ||
outstanding_handles: Arc<AtomicU32>, | ||
// Ensure this type cannot be sent between threads. |
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.
Could impl !Send for JSEngine{}
be used for that purpose?
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.
error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now
--> src/rust.rs:181:1
|
181 | impl !Send for JSEngine {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/13231
= help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable
I'd rather not introduce nightly-only features to this crate.
The idea of making shutdown be a blocking operation is interesting, but I think I'd rather not make that a requirement of using this crate. It's not difficult to imagine a consumer writing code that uses this API that ends up creating a deadlock by not ensuring that all of the engine handles are disposed of before attempting to shutdown. I would rather provide an API that panics by default and allow consumers to build their own blocking shutdown behaviour on top of it, like servo/servo#24862 does for Servo. |
Ensure SpiderMonkey shuts down cleanly This is the alternate solution that I described in #24845. Given how much simpler the resulting code is, I'm now much more in favour of this design. Depends on servo/rust-mozjs#487. --- - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #21696 and fix #22276 - [x] There are tests for these changes
Yes that makes sense, although it's not clear to me how a non-blocking use, or a blocking use that isn't a spinlock waiting for it to return It would be possible for a consumer to deadlock on a blocking I guess either way for the API could be a valid choice thought... |
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.
Is it worth dedicating a thread to JS engine creation and destruction? That would make the API a bit cleaner, but at the cost of yet another thread. I'll leave that up to you, this implementation LGTM.
@bors-servo r=asajeffrey |
📌 Commit c8c1453 has been approved by |
Prevent initializing and shutting down SpiderMonkey from different threads Based on [this comment](https://github.com/servo/mozjs/blob/e21c05b415dfc246175ff8d5fc48b0e8c5b4e9e9/mozjs/js/public/Initialization.h#L19-L23), it appears that JS_Init and JS_ShutDown need to be called on the same thread. These changes make JSEngine a non-sendable type, and add JSEngineHandle as a sendable type that allows verifying that all outstanding consumers of the engine are dropped before shutting down.
☀️ Test successful - checks-travis, status-appveyor |
Ensure SpiderMonkey shuts down cleanly This is the alternate solution that I described in #24845. Given how much simpler the resulting code is, I'm now much more in favour of this design. Depends on servo/rust-mozjs#487. --- - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #21696 and fix #22276 - [x] There are tests for these changes
Ensure SpiderMonkey shuts down cleanly This is the alternate solution that I described in #24845. Given how much simpler the resulting code is, I'm now much more in favour of this design. Depends on servo/rust-mozjs#487. --- - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #21696 and fix #22276 - [x] There are tests for these changes
Based on this comment, it appears that JS_Init and JS_ShutDown need to be called on the same thread. These changes make JSEngine a non-sendable type, and add JSEngineHandle as a sendable type that allows verifying that all outstanding consumers of the engine are dropped before shutting down.