* Fix race condition in Worker destruction
During shutdown, the main script thread calls
JS_RequestInterruptCallback(cx) for each worker thread it owns
where cx is the JSContext* created for that worker.
Although JS_RequestInterruptCallback is safe to call
from threads other than the worker thread, it is possible
the JSContext* has already been destroyed
For example, as noted in #30022, since the main thread sets
the worker's `closing` flag to true to signal termination before it
calls JS_RequestInterruptCallback, we can have a race condition
where the worker exits its event loop when `closing` flags is set
and then it (worker thread) destroys its own JSContext and JSRuntime.
When the main thread resumes, it will call
JS_RequestInterruptCallback for the worker's context, leading to
a use-after-free bug.
This patch solves this issue by improving the existing
`ContextForRequestInterrupt` abstraction used for sharing the Worker's
associated JSContext* with the parent script thread.
Instead of simply wrapping a plain `*mut JSContext`, we now wrap the
`*mut JSContext` in a nullable mutex i.e Mutex<Option<*mut JSContext>>
The mutex lock needs to be held by the parent thread when it
calls JS_RequestInterruptCallback.
Similary, before the worker destroys its JSContext, it locks and
sets the Option to None, signaling that the JSContext can no longer
be used for interrupting the worker.
This patch also fixes the issue in #30052 by enforcing the use
of ContextForRequestInterrupt abstraction which ensures the correct
JSContext is used by the main thread when Worker.terminate is called.
Fixes #30022, #30052
* Fix Worker.importScripts to handle termination
Fixing #30052 uncovered this issue in the implementation
of `importScripts` method. After the fix for #30052,
the WPT test `/workers/Worker-terminate-forever-during-evaluation.html`
started to crash because when evaluation doesn't succeed
`importScripts` always returns Error::JSFailed code to the caller,
which indicates that there is a Dom/JS exception to be thrown. However,
this is not true when the script is terminated, which causes
the generated binding layer for 'importScript` to fail
the assertion that there is a pending exception.
This patch makes `importScripts` work similar to the [logic that
evaluates the top-level script][1] of the Worker - it simply prints
`evaluate_script failed - (terminated)' if the worker is terminating
[1]:
|
||
---|---|---|
.cargo | ||
.github | ||
.vscode | ||
components | ||
docs | ||
etc | ||
ports | ||
python | ||
resources | ||
support | ||
tests | ||
third_party | ||
.clang-format | ||
.flake8 | ||
.gitattributes | ||
.gitignore | ||
.hgignore | ||
.mailmap | ||
Cargo.lock | ||
Cargo.toml | ||
CLOBBER | ||
CONTRIBUTING.md | ||
dependencyci.yml | ||
Info.plist | ||
LICENSE | ||
mach | ||
mach.bat | ||
PULL_REQUEST_TEMPLATE.md | ||
README.md | ||
rust-toolchain.toml | ||
rustfmt.toml | ||
servo-tidy.toml | ||
servobuild.example |
The Servo Parallel Browser Engine Project
Servo is a prototype web browser engine written in the Rust language. It is currently developed on 64-bit macOS, 64-bit Linux, 64-bit Windows, and Android.
Servo welcomes contribution from everyone. See
CONTRIBUTING.md
and HACKING_QUICKSTART.md
for help getting started.
Visit the Servo Project page for news and guides.
Build Setup
If these instructions fail or you would like to install dependencies manually, try the manual build setup.
macOS
- Install Xcode
- Install Homebrew
- Run
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- Run
pip install virtualenv
- Run
./mach bootstrap
Note: This will install the recommended version of GStreamer globally on your system.
Linux
- Run
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- Install Python and virtualenv
- Debian-like: Run
sudo apt install python3-virtualenv python3-pip
- Fedora: Run
sudo dnf install python3 python3-virtualenv python3-pip python3-devel
- Arch: Run
sudo pacman -S --needed python python-virtualenv python-pip
- Gentoo: Run
sudo emerge dev-python/virtualenv dev-python/pip
- Debian-like: Run
- Run
./mach bootstrap
Windows
- Download and run
rustup-init.exe
then follow the onscreen instructions. - Install chocolatey
- Run
mach bootstrap
- This will install CMake, Git, Ninja, Python and the Visual Studio 2019 Build Tools via choco in an Administrator console. It can take quite a while.
- If you already have Visual Studio 2019 installed, this may not install all necessary components. Please follow the Visual Studio 2019 installation instructions in the manual setup.
- Run
refreshenv
See also Windows Troubleshooting Tips.
Cloning the Repo
Your CARGO_HOME needs to point to (or be in) the same drive as your Servo repository (See #28530).
git clone https://github.com/servo/servo
cd servo
Building
Servo is built with Cargo, the Rust package manager. We also use Mozilla's Mach tools to orchestrate the build and other tasks. You can call Mach like this:
On Unix systems:
./mach [command] [arguments]
On Windows Commandline:
mach.bat [command] [arguments]
The examples below will use Unix, but the same applies to Windows.
The Rust compiler
Servo's build system uses rustup.rs to automatically download a Rust compiler.
This is a specific version of Rust Nightly determined by the
rust-toolchain
file.
Normal build
To build Servo in development mode. This is useful for development, but the resulting binary is very slow:
./mach build --dev
./mach run tests/html/about-mozilla.html
Release build
For benchmarking, performance testing, or real-world use.
Add the --release
flag to create an optimized build:
./mach build --release
./mach run --release tests/html/about-mozilla.html
Checking for build errors, without building
If you’re making changes to one crate that cause build errors in another crate, consider this instead of a full build:
./mach check
It will run cargo check
, which runs the analysis phase of the compiler
(and so shows build errors if any) but skips the code generation phase.
This can be a lot faster than a full build,
though of course it doesn’t produce a binary you can run.
Building for Android target
For ARM (armv7-linux-androideabi
, most phones):
./mach build --release --android
./mach package --release --android
For x86 (typically for the emulator):
./mach build --release --target i686-linux-android
./mach package --release --target i686-linux-android
Running
Run Servo with the command:
./servo [url] [arguments] # if you run with nightly build
./mach run [url] [arguments] # if you run with mach
# For example
./mach run https://www.google.com
Commandline Arguments
-p INTERVAL
turns on the profiler and dumps info to the console everyINTERVAL
seconds-s SIZE
sets the tile size for painting; defaults to 512-z
disables all graphical output; useful for running JS / layout tests-Z help
displays useful output to debug servo
Keyboard Shortcuts
Ctrl
+L
opens URL prompt (Cmd
+L
on Mac)Ctrl
+R
reloads current page (Cmd
+R
on Mac)Ctrl
+-
zooms out (Cmd
+-
on Mac)Ctrl
+=
zooms in (Cmd
+=
on Mac)Alt
+left arrow
goes backwards in the history (Cmd
+left arrow
on Mac)Alt
+right arrow
goes forwards in the history (Cmd
+right arrow
on Mac)Esc
orCtrl
+Q
exits Servo (Cmd
+Q
on Mac)
Runtime dependencies
Linux
GStreamer
>=1.16gst-plugins-bad
>=1.16
Developing
There are lots of mach commands you can use. You can list them with ./mach --help
.
The generated documentation can be found on https://doc.servo.org/servo/index.html