diff --git a/Cargo.lock b/Cargo.lock index ea625f81909b..d625423a6ead 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2791,6 +2791,7 @@ dependencies = [ "openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)", "pixels 0.0.1", "profile_traits 0.0.1", + "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "servo_allocator 0.0.1", diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml index af3b049cda30..d21dbd56f0e5 100644 --- a/components/net/Cargo.toml +++ b/components/net/Cargo.toml @@ -44,6 +44,7 @@ net_traits = {path = "../net_traits"} openssl = "0.10" pixels = {path = "../pixels"} profile_traits = {path = "../profile_traits"} +rayon = "1" serde = "1.0" serde_json = "1.0" servo_allocator = {path = "../allocator"} diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index 7a9dd49139c5..376d51618644 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -398,6 +398,7 @@ pub struct CoreResourceManager { devtools_chan: Option>, swmanager_chan: Option>, filemanager: FileManager, + fetch_pool: rayon::ThreadPool, } impl CoreResourceManager { @@ -407,11 +408,16 @@ impl CoreResourceManager { _profiler_chan: ProfilerChan, embedder_proxy: EmbedderProxy, ) -> CoreResourceManager { + let pool = rayon::ThreadPoolBuilder::new() + .num_threads(16) + .build() + .unwrap(); CoreResourceManager { user_agent: user_agent, devtools_chan: devtools_channel, swmanager_chan: None, filemanager: FileManager::new(embedder_proxy), + fetch_pool: pool, } } @@ -446,42 +452,37 @@ impl CoreResourceManager { _ => ResourceTimingType::Resource, }; - thread::Builder::new() - .name(format!("fetch thread for {}", request_builder.url)) - .spawn(move || { - let mut request = request_builder.build(); - // XXXManishearth: Check origin against pipeline id (also ensure that the mode is allowed) - // todo load context / mimesniff in fetch - // todo referrer policy? - // todo service worker stuff - let context = FetchContext { - state: http_state, - user_agent: ua, - devtools_chan: dc, - filemanager: filemanager, - cancellation_listener: Arc::new(Mutex::new(CancellationListener::new( - cancel_chan, - ))), - timing: Arc::new(Mutex::new(ResourceFetchTiming::new(request.timing_type()))), - }; - - match res_init_ { - Some(res_init) => { - let response = Response::from_init(res_init, timing_type); - http_redirect_fetch( - &mut request, - &mut CorsCache::new(), - response, - true, - &mut sender, - &mut None, - &context, - ); - }, - None => fetch(&mut request, &mut sender, &context), - }; - }) - .expect("Thread spawning failed"); + self.fetch_pool.spawn(move || { + let mut request = request_builder.build(); + // XXXManishearth: Check origin against pipeline id (also ensure that the mode is allowed) + // todo load context / mimesniff in fetch + // todo referrer policy? + // todo service worker stuff + let context = FetchContext { + state: http_state, + user_agent: ua, + devtools_chan: dc, + filemanager: filemanager, + cancellation_listener: Arc::new(Mutex::new(CancellationListener::new(cancel_chan))), + timing: Arc::new(Mutex::new(ResourceFetchTiming::new(request.timing_type()))), + }; + + match res_init_ { + Some(res_init) => { + let response = Response::from_init(res_init, timing_type); + http_redirect_fetch( + &mut request, + &mut CorsCache::new(), + response, + true, + &mut sender, + &mut None, + &context, + ); + }, + None => fetch(&mut request, &mut sender, &context), + }; + }); } fn websocket_connect( diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 44be53a4de04..a29a6bb5c5a6 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -13052,6 +13052,19 @@ {} ] ], + "mozilla/fetch_cannot_overwhelm_system.window.js": [ + [ + "mozilla/fetch_cannot_overwhelm_system.window.html", + { + "script_metadata": [ + [ + "title", + "Ensure multiple fetch do not crash the browser." + ] + ] + } + ] + ], "mozilla/first-reflow-sheet-assert.html": [ [ "mozilla/first-reflow-sheet-assert.html", @@ -20057,6 +20070,10 @@ "0ba1ce0d5577de68e5e8ff3acbce52043e7dee43", "testharness" ], + "mozilla/fetch_cannot_overwhelm_system.window.js": [ + "989231e9caedd099f5212bd2f9d377c83f929a22", + "testharness" + ], "mozilla/first-reflow-sheet-assert.html": [ "268af6d333f04adc35974ca3f2e9ebb29783fd2e", "testharness" diff --git a/tests/wpt/mozilla/meta/mozilla/fetch_cannot_overwhelm_system.window.js.ini b/tests/wpt/mozilla/meta/mozilla/fetch_cannot_overwhelm_system.window.js.ini new file mode 100644 index 000000000000..37bb7100b8ce --- /dev/null +++ b/tests/wpt/mozilla/meta/mozilla/fetch_cannot_overwhelm_system.window.js.ini @@ -0,0 +1,3 @@ +[fetch_cannot_overwhelm_system.window.html] + expected: + if os == "linux": CRASH diff --git a/tests/wpt/mozilla/tests/mozilla/fetch_cannot_overwhelm_system.window.js b/tests/wpt/mozilla/tests/mozilla/fetch_cannot_overwhelm_system.window.js new file mode 100644 index 000000000000..989231e9caed --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/fetch_cannot_overwhelm_system.window.js @@ -0,0 +1,15 @@ +// META: title=Ensure multiple fetch do not crash the browser. + +async_test(function(t) { + onload = t.step_func(function() { + var step; + var xhr + var url = '/'; + t.step_timeout(t.step_func_done(), 10); + for (step = 0; step < 5000; step++) { + xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.send(); + } + }); +});