mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
ebda1f73c4
- Bug 1208341 - Make NativeObject::goodElementsAllocationAmount fallible. r=Waldo (64eac96aa2) - minor reformat (95d27e5332) - Bug 1214049 - Use ReportOutOfMemory in NativeObject::goodElementsAllocationAmount. r=Waldo (6779dd81c6) - Bug 1206700 - Fix an bug in property assignment, recently exposed by Reflect.set. r=waldo (0a7484ab70) - Bug 1186810 (part 1) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=nsm. (05a550c94f) - Bug 1186810 (part 2) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=nsm. (f1659abf38) - Bug 1186810 (part 3) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=nsm. (cda73950f3) - Bug 1186810 (part 4) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=nsm. (555e83bacb) - Bug 1186810 (part 5) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=nsm. (c9520dbc5f) - Bug 1186810 (part 6) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=khuey. (24fcdfd772) - Bug 1186810 (part 7) - Replace nsBaseHashtable::EnumerateRead() calls in dom/workers/ with iterators. r=khuey. (657cd575fb) - Bug 1186810 (part 8) - Replace nsBaseHashtable::Enumerate() calls in dom/workers/ with iterators. r=khuey. (0ff6a5e5ff) - Bug 1205020 - Disable optimizations in TestTuple.cpp since it breaks the build on VS2013 Windows 10. r=froydnj (1c98d8485c) - Bug 1199068 - Soothe a unused variable warning in TestSplayTree.cpp. r=nfroyd (d4d4ab56fe) - Bug 1209751 - Make sync decoding more reliable when nsImageRenderer is used with -moz-element. r=roc (95c99bb907) - Bug 1209731 - Return DrawResult::NOT_READY from PaintBackgroundWithSC if we couldn't prepare the nsImageRenderer. r=tn (8bd98872cb) - Bug 1209715 - Add operator overloads for combining DrawResults. r=tn (f3a9806d03) - Bug 1209725 - Use DrawResult combining operators in nsCSSRendering::PaintBackgroundWithSC. r=tn (420cfde63e) - Bug 1211363. Calculate min inset blur with max border radius. r=mstange (5e408bc67f) - Bug 1213545. Carry x,y offsets with inset box shadows. r=mstange (52c20715bc) - Bug 1209739 - Make nsImageRenderer::PrepareImage() fail unless an image has STATUS_LOAD_COMPLETE. r=tn (c1cc4d79d8) - Bug 1209765 (Part 1) - Support sync decoding of border-image in nsCSSRendering. r=tn (3a54b7d117) - Bug 1209765 (Part 2) - Support sync decoding and track draw results in nsDisplayBorder. r=tn (03abe63e67) - Bug 1209765 (Part 3) - Support sync decoding and track draw results when drawing borders in nsButtonFrameRenderer. r=tn (107b9bb851) - Bug 1209765 (Part 4) - Support sync decoding and track draw results when drawing borders in nsFieldSetFrame. r=tn (16fd30aba3) - Bug 1209765 (Part 5) - Support sync decoding and track draw results when drawing borders in nsRangeFrame. r=tn (289de3c17e) - Bug 1209765 (Part 6) - Support sync decoding and track draw results when drawing borders in nsColumnSetFrame. r=tn (0317d6a914) - Bug 1143267 - Make nsDisplayAltFeedback use nsGenericImageGeometry. r=tn (8fc6372d48) - Bug 1176081. Add a pref to control drawing of the image loading place holder icon and border, and disable it. r=seth (792e8ec9b3) - Bug 1209765 (Part 7) - Support sync decoding and track draw results when drawing borders in nsImageFrame. r=tn (70d9af60a3) - Bug 1209765 (Part 8) - Support sync decoding and track draw results when drawing borders in MathML code. r=tn (555bff2635) - Bug 1209765 (Part 9) - Support sync decoding and track draw results when drawing borders in nsTableFrame. r=tn (d242dc5c79) - Bug 1209765 (Part 10) - Support sync decoding and track draw results when drawing borders in nsGroupBoxFrame. r=tn (a7187cfa5d) - Bug 1209765 (Part 11) - Support sync decoding and track draw results when drawing borders in nsTreeBodyFrame. r=tn (21bd2b3285) - Bug 1209765 (Followup) - Add very minor fuzz to underline-button-2.html on OS X 10.10. r=me (04cff3c2ff) - Bug 1209765 (Followup) - Add very minor fuzz to underline-button-1.html on OS X 10.10. r=me DONTBUILD (187fdb4106) - Bug 1217069 - Don't attempt to mis-optimize JSON.stringify's filter-list creation for replacer arrays with trailing holes. r=arai (04fb907d42) - Bug 1156463 - Add a preference option to disable the scale transform applied to MathML operators. r=karl (415a041117) - Bug 1174143 - Remove private tables for Standard Symbols L and MathJax fonts. r=karlt (1f58d14229) - Bug 1222297 - Use channel->Open2() in netwerk/base/nsNetUtil.cpp (r=sicking) (cbd12ebb0a) - Bug 1139709. Remove unused parameters from nsMathMLChar::GetMaxWidth. r=mats (6ea90a0a02) - Bug 1160635 patch 1 - Add reftests. r=dholbert (b58f8fd7fa) - Bug 1160635 patch 2 - Stop making image resizing optimization when image has percent width or height. r=dholbert (9ae3621baf) - Bug 1156097 - Make nsImageFrame::mImageMap an nsRefPtr; r=roc (b49157e424) - Bug 1176156. Make sure images are asked to decode if we are drawing the alt feedback instead of the image. r=seth (8d7a09622e) - Bug 1207355 (Part 2) - Stop requesting decodes in nsImageLoadingContent. r=tn (c781285098) - Bug 1207355 (Part 3) - Request decodes intelligently in nsImageFrame. r=tn (c61b7591fb) - Bug 1156028 - Teach clang-analyzer about XPCOM assertion macros; r=froydnj (4d8b7ecf03) - Bug 1207355 (Part 4) - Request decodes intelligently in nsBulletFrame. r=tn (2d7ced9c0f) - Bug 1207355 (Part 5) - Request decodes intelligently in MultipartImage. r=tn (c0cb580838) - Bug 1207355 (Part 6) - Only respect StartDecoding() in imgRequest/imgRequestProxy. r=tn (0e108cda4c) - Bug 1207355 (Part 7) - Only trigger intrinsic size decode in FinalizeDecoder() if StartDecoding() was called. r=tn (a71fc0d1b7) - Bug 1207355 (Part 8) - Remove imgIContainer::RequestDecode() and imgIRequest::RequestDecode(). r=tn (fbce1ccbe1) - Bug 1215596 - outline: auto; will render as outline: solid; when disabled. r=roc (b8ea369628) - Bug 1180966. Remove code that made no sense. r=mstange (eac62913ef) - Bug 1217905. Don't transform dest rects if destination context has a rotation with inset box shadows. r=mstange (53cf4d6f86) - Bug 1189010. In ScrollFrameHelper::BuildDisplayList decide if we are building a scrollable layer before we call AppendScrollPartsTo because it needs this information. r=mstange (a008c7e34d) - Bug 1204535 - Flatten conditional structure one level. r=tn (152ff398a0) - Bug 1204535 - Remove no-op code. r=tn (95d17e64c3) - Bug 1204535 - Collapse redundant conditional block. r=tn (d0e90b8d80) - Bug 1204535 - Rename usingDisplayport to usingDisplayPort for consistency. r=tn (516757a933) - Bug 1204535 - Relocate comment to go with the line of code it's commenting. r=tn (70ae0c5e71) - Bug 1204535 - Hoist out the code to initially compute usingDisplayPort. r=tn (4a5336a480) - Bug 1210578. Part 1. Rename mShouldBuildScrollableLayer to mWillBuildScrollableLayer to better capture the meaning of the variable. r=mstange (d13bb100f4) - Bug 1210578. Part 2. Rename shouldBuildLayer to couldBuildLayer to better reflect it's actual meaning. r=mstange (ae21c687c2) - Bug 1151663 - Only call GetOrMaybeCreateDisplayPort() in nsLayoutUtils::PaintFrame() if we are using containers for root scroll frames. r=tn (2bef3f9457) - Bug 1195431 - Small refactoring to use conditionals consistently. r=tn (897eb0f42a) - Bug 1167069 - Initialize nsPluginFrame::mInstanceOwner to null. r=jmathies (6ce1fcb8c2) - Bug 1137944 - Add support for hiding plugin windows during async dom scroll operations managed in the content process. r=roc (730a0ed004) - Bug 1210578. Part 3. Create DecideScrollableLayer that encapsulates all logic to create display ports and build scrollable layers. r=mstange (994ac6ec5e) - Bug 376679 part.1 Change the result of EventStateManager::ComputeScrollTarget() from nsIScrollableFrame* to nsIFrame* r=smaug (914878edbd) - Bug 376679 part.2 EventStateManager should treat plugin frame as scrollable frame if the plugin wants to handle wheel events as default action r=smaug (58c146b7ba) - Bug 376679 part.3 Compute default action target frame for wheel event before deciding the action because plugin should decide what is the default action when the target is a plugin frame r=smaug (334cbfcf53) - Bug 376679 part.4 Manage wheel transaction at sending a wheel event to target plugin r=smaug (d76062a429) - Bug 376679 part.5 nsPluginInstanceOwner::ProcessEvent() should create WM_MOUSE*WHEEL message from WidgetWheelEvent data r=smaug+jimm (56ee6bdf90) - Bug 376679 part.6 nsPluginInstanceOwner::ProcessEvent() should refer both deltaMode and system scroll amount settings when it generates WM_MOSUE*WHEEL messages r=jimm (927cb10a3b) - Bug 1145546 - Add missing nsBidiPresUtils.h include to nsGfxScrollFrame.cpp to fix non-unified bustage. r=jfkthame (af4043c024) - Bug 1137944 - Add plugin window handling for apz related notifications received by the content process. r=mstange (798e9676fd) - Bug 1208819 - Fix irregexp overrecursion check to ignore interrupts. r=bhackett (c845e65a2e) - Bug 1218640 - IonMonkey: MIPS64: Add support into irregexp. r=arai (613ddd95ef) - Bug 1211964 - Fix a couple of OOM handling issues in regexp code r=terrence (bb269eef3e) - Bug 1200734 - Use stable hashing for LiveScopesMap; r=shu (1d717c8f53) - Bug 1223853 - Use stable hashing for ObjectValueMap; r=jonco (c91f3b1b21) - Bug 1223863 - Use stable hashing for WeakGlobalObjectSet; r=jonco (eb29e841f1) - Bug 1223918 - Use stable hashing for WatchPointMap; r=jonco (7a69630c83) - Bug 1212011 - Replace more uses of CrashAtUnhandlableOOM() with AutoEnterOOMUnsafeRegion r=terrence (0079439d90) - Bug 1224347 - Use stable hashing for DebuggerWeakMaps; r=jonco (d2a627e077) - Bug 1219418 - Always access minEmptyChunkCount under the GC lock; r=jonco (f67f74ca57) - Bug 1202923 - Encapsulate GC begin and end notification callbacks in an RAII guard; r=jonco (46f63fd090) - Bug 1212624 - Tests for LinkedList, r=Waldo (3d48b12918) - Bug 1215752 - Weakmap refactoring, r=terrence (90cbf4d294) - Bug 1216744 - Move weakKeys to the zone, r=terrence (5fdb1d57bf) - Bug 1215336 - Measure unmark gray time, r=terrence (278e0ee562) - Bug 1211939 - Don't call JSRuntime::onOutOfMemory from helper threads. r=jonco (86c6906421) - Bug 1218638 - IonMonkey: MIPS64: Add support into jit/shared. r=lth (e4f2904c53) - Bug 1216277 - Don't assert properties of the buffer location if the assembler is out of memory r=jandem (65556e83ce) - Bug 1211962 - addNativeToBytecodeEntry: Check that the masm.currentOffset() returns a valid result. r=djvj (3c5723c65a) - Bug 1090957 - IonMonkey: Add temp registers for mips atomics. r=lth (00f23fe2e9) - Bug 1218967 - Do not stop executing autospider.sh on test failure. r=sfink (75f912efbb) - Bug 1213881 - Run jsapi-tests in the arm64-sim autospider. r=sfink (2e731f14e7) - Bug 1216607 - Fix assertion failure ARM assembler on OOM r=jandem (0bc2dcb5db) - Bug 1209515 part 1 - IonBuilder: Attach hit counts on the MIRGraph. r=bhackett (f5448d9596) - Bug 1209515 part 2 - Ensure that MPhi removal considers removed uses. r=bhackett (95de413c50) - Bug 1209515 part 3 - IonMonkey: Add branch pruning based on code coverage counters. r=bhackett (fb71022658) - Bug 1209515 part 0 - Move callerResumePoint field next to other resume points of basic blocks. r=bbouvier (394b52860d) - Bug 1209515 part 4 - Increment code coverage counters on bailouts. r=bhackett (22edac5c24) - Bug 1209515 part 5 - Ensure that we recompile when we have frequent bailouts caused by the first execution. r=jandem (bca0fa4118) - Bug 1209515 part 7 - IonBuilder: pushLoop should not infer the continuepc from the entry block. r=jandem (025d10fd57) - Bug 1209515 part 8 - IonBuilder: newOsrPreheader should not use the hit-count of the loop. r=jandem (5db05ef17f) - Bug 1209515 part 9 - IonBuilder: Loop header should use the hit count of the loop, instead of before the loop. r=jandem (b259b490bf) - Bug 1209515 part 10 - Prevent PruneUnusedBranches from being greedy while removing branches which have only be visited a few times. r=bhackett (4a1a7b34b6) - Bug 1209515 part 11 - Increase JitSpewer mask size to avoid overflow. r=bbouvier (28546de94e) - Bug 1219401 - Don't call script->hasIonScript() off-thread, fixes a TSan race. r=h4writer (8f31724484) - Bug 1172076 - Assert that SnapshotIterator::initInstructionResults always match the recover instructions data. r=jandem (6ed0eebc65) - Bug 1209260 - Don't use sincos on iOS r=npb (eaa3cacac7) - Bug 1222499 - "JitSpew/IonSpew: warmupCounter should use PRIu32 instead of PRIuSIZE". r=nbp (50b80b985a) - Bug 1216182: Rename MODE_MASK to MODE_BITS_MASK, r=hv1989 (f28e461d94) - Bug 1137944 - Add a pref to control plugin window hiding. r=roc (691dc99b94) - Bug 1214878 - When async scrolling with e10s hide windowed plugins in sub documents. r=roc (79c0eac459) - Bug 1215434 part.1 If scroll target is a plugin frame, EventStateManager::PostHandleEvent() should send the wheel event to the plugin frame even if APZC already handled it r=smaug (f2e8e33d7f) - Bug 1215434 part.2 Add plugin frame rect to dispatch-to-content region if it wants to handle wheel event as default action r=mstange (dbecb1e256) - Fix inactive scroll frames sometimes creating very large, incorrect hit regions. (bug 1190112, r=tn) (2056d8d63e) - Fix scrollbars on subframes not directing APZ events to the correct scrollframe. (bug 1213324, r=tn) (0594923ab2) - Bug 1182017. Call Send__delete__ immediately rather than through an event. r=nical (90714b065b) - Bug 1212656 - ARM64: Fix automation build failures. (r=efaust) (5695518dd1) - Bug 1137944 - Simplify the api associated with hiding e10s plugin widgets. r=roc (dfbfda4d31) - Bug 1137944 - Fire before and after composite events. r=matt.woodrow (0048aeb8cb) - Bug 1201660 - When layer tree updates get dropped, hide plugins associated with the tree. Fixes a bug where we were hiding all plugins associated with the window. r=matt.woodrow (9352150c73) - Bug 1137944 - Backout compositor bits (cset b4711fa5f734) which caused a telemetry metric regression. r=backout (241659d6a8) - Bug 1127270: Only acquire a hold on the compositor thread once the channel for a parent actor has been succesfully connected. r=nical (1d1b077d68) - Bug 1207270 - Ensure that the TaskThrottler objects are created on the main thread. r=botond (b43af025f1) - Bug 1194876 - Add test. r=botond (440c72ec81) - Bug 1152051 - Gtest. r=Cwiiis,kats (011f066f37) - Bug 1144112 - Update the FlingStop tests to check if events are flowing properly after the fast-motion blocks are done. r=botond (25f71629d7) - Bug 1092128 - Ensure that when touch-action is enabled the gtests always provide default touch behaviours where expected. r=botond (3f0d1229f3) - Bug 1144112 - Only set the default allowed touch behaviour if the event is not consumed, to have the tests better reflect reality. r=botond (1548bd14bb) - Bug 1163845 - Unify handling of time in APZ gtests. r=kats (b73a16ef5e) - Bug 1159398 - Set the controller thread when running APZ gtests. r=dvander (96b551036e) - Bug 1159985 - Gtest. r=kats (23d7d86492) - Bug 1159985 - In APZ gtests, allow panning in both directions. r=kats (14f4b1156a) - Bug 1169695 - Make the test timestamp privately held by the MockContentControllerDelayed. r=botond (ffe04249c1) - Bug 1198900 - Add a gtest to ensure we don't crash when prevent-defaulting a wheel event. r=botond, a=topcrash (c9e5993f18) - Bug 1169690 - Gtests. r=kats (7e825b34ac) - Bug 1207270 - Update tests to ensure that TaskThrottlers are created as appropriate. r=botond (7bb6f1f406) - Bug 1169695 - Ensure timed tasks are dispatched appropriately when advancing the time. r=botond (af1fbe0a85) - Bug 1204837, Part 1: Make ClosingService thread Nuwa-friedly. r=khuey (eb790b5215) - Bug 1204837, Part 2: Cloned ImageBridgeParent and CompositorParent should hold a reference to the compositor thread. r=nical (cd742df2e2) - Bug 1205016: double ClosingService thread stack size to avoid stack overflow r=glandium (cb9acc828f) - Bug 1163570 - Ignore pending plugin updates and hide plugin windows when a remote layer tree associated with a tab is no longer in use. r=roc (ae852ad442) - Bug 1196539 - Apply plugin config using AutoResolveRefLayers during composition. r=matt.woodrow (12dbdb6222) - Bug 1137944 - Cache compositor plugin update data to avoid sending updates to the main thread when the data doesn't change. r=roc (63c503d2f6) - Bug 1137944 - On Windows defer composition until we receive confirmation plugin window metrics have been updated. r=roc (39d5786519) - Bug 1137944 - Move plugin window metrics updates to a point during comososition where we know the remote layer tree is hooked up to the chrome layer tree. r=matt.woodrow (a32f77ffb1) - Bug 1213671 - CompositorParent::UpdatePluginWindowState should always return an accurate result indicating when an ipc request for plugin geometry updates was sent. r=roc (311e65a8ce) - Bug 1214267 - Send the side to which fixed-pos items are attached so that we can move them in the compositor more correctly when the viewport size is changing. r=mattwoodrow (fa2de207cd) - Bug 1209964 - In AlignFixedAndStickyLayers(), properly handle the case where a fixed or sticky layer is its own subtree root and has a local transform. r=kats (1a6922699a) - Bug 1213762 - Clear AsyncCompositionManager::mIsFirstPaint on non-Android platforms, too. r=mstange (c4cf2b722a) - Bug 1223436 - Fix AsyncCompositionManager so that mLayersUpdated is only set to false after SyncFrameMetrics has been called. r=kats (f3fa84325b) - bits of 1073545 (3bc7d76081) - Bug 1213795, Part 1: Don't fire timers in the Nuwa process to fix test case test_NuwaProcessDeadlock.html. r=khuey (5ebca946e5) - Bug 1213795, Part 2: Fix protocol cloning of actor CrossProcessCompositorParent. r=khuey (92969e2b06) - spacing (f4857ed898) - Bug 1213758 - Aquire the inderect layer trees data lock during plugin window update calculations. r=matt.woodrow (ae70d955ec) - Bug 1208502 - Use more smart pointers in XULDocument. r=smaug (20a92d72e8) - Bug 1193086 - Remove some null checks of infallible new code in XUL. r=baku (2f463c5a3d) - Bug 1217190 - Make PrintingParent return an nsresult when attempting to show print progress. r=bobowen (addf31f3a7) - Bug 1217190 - Make sure to initialize outparam in PrintingParent::RecvShowProgress. r=bobowen (f6c11a0181) - Bug 1152921 - Don't send an uninitialized PrintData over IPC when cancelling print dialog (or failing ShowPrintDialog for other reasons). r=mconley (4ea146ccf1) - Bug 1178233 - [non-e10s] The update process doesn't work within about:serviceworkers in non-e10s mode. r=baku (7a08441bec) - Bug 929846 - Considering key size when calculating quota usage. r=jdm (a97ddc7906) - Bug 1194049 - Part 3: support device update; r=fabrice (6ba600a03d) - Bug 1194049 - Part 1: add thread assertion; r=schien (68c4658ae0) - Bug 1194049 - Part 2: add discovery timeout support; r=schien (14f5f537d5) - Bug 1194049 - Part 4: clear discovered devices when re-discover; r=schien (e2ecdb573f) - Bug 1136565 - report session request from device provider. r=xeonchen,junior,seanlin. (19daa67751) - Bug 1216398 - support non-discoverable controlling device. r=junior,xeonchen. (7383401dbc) - Bug 1200132 - Use adderss to create socketTransport, r=schien, junior (263d253562) - Bug 1200132 - Part1: Get address info after service resolved, r=mcmanus (9bcc344d20) - Bug 1200132 - Part2: Get IP address by calling InetAddress.getHostAddress(), r=mcmanus, rnewman (502c243314) - Bug 1173334: Open nfcd connections with socket type SOCK_SEQPACKET, allstars.chh (03a11dc077) - Bug 1173802: Move NFC socket and messaging code into |NfcConsumer|, r=allstars.chh (f92946b40e) - Bug 1173802: Run |NfcConsumer| on NFC thread, r=allstars.chh (87989483a7) - Bug 1173802: Clean up |NfcEventDispatcher|, r=allstars.chh (87f58b7310) - Bug 1173802: Replace |assertIsNfcServiceThread| with thread-safe checks, r=allstars.chh (1a6a76ae05) - Bug 1173802: Store global NFC service in ref-counted variable, r=allstars.chh (a33c025976) - Bug 1188639 - Fix typo in BrowserElement.webidl and add tests for it. r=yoshi,bz (7b657a335d) - Bug 1175387 - close file descriptor after detached from STS. r=mcmanus (377943bad5) - Bug 1190069 - Fix uninitialized variable in MDNSResponderOperator.cpp. r=xeonchen (ebf47b613e) - Bug 1217807 - Part 1: use ServiceWatcher to extend life cycle of mDNS operators; r=schien (70201259d2) - missing namespace (c6bccda1e5) - Bug 1209843 - Stop checking for UNKNOWN_APP_ID in all places except those where AppId() is explicitly queried. r=sicking (e364223906) - Bug 1168337: Kill the processes on startup of the Nuwa test case fix the abort in the preallocated process. r=khuey (501a30cb9b) - Bug 1202424 - Free shared memory when IPC system shuts down, not after. r=mrbkap (f718cbf801) - Bug 1209987 - webrtc.org Engine creation and destruction should happen on the WebRTC threads. r=jesup (4bbab795cf) - Bug 1214675 - Factor out cleanup functions to avoid deadlock/dispatch-without-IPC. r=jesup (bd466c85e4) - Bug 1210560 - Part 2: Convert some simple users to use PushGroupForBlendBack. r=jrmuizel (158b532f9f) - Bug 1174785 - Part 0: Use mozilla/StaticPtr.h in signaling. r=jesup (c98ec23ee0) - Bug 1174785 - Part 1: Add LogModule, LogModuleManager, and LazyLogModule. r=froydnj (e797bca424) - Bug 1195867 - Hoist StateWatching and StateMirroring into XPCOM. r=froydnj (a62fbbf749) - Bug 1194631 - Make firefox build with --disable-logging. r=jrmuizel (ba8238dc42) - Bug 1174785 - Part 2: Convert xpcom over to LogModule. r=froydnj (ccb119d496) - Bug 1205237 - Part 2: add PresentationNetworkHelper; r=schien (be47702ffe) - Bug 1205237 - Part 3: get self Wi-Fi IP address; r=seanlin (f31163e895) - Bug 1217683 - Add sendIceCandidate and implement |close(aReason)| in TCPControlChannel. r=fabrice (0004ea93f1) - Bug 1217807 - Part 2: Handle network online/offline event in TCPPresentationServer; r=junior (48c9236adb) - Bug 1217807 - disable MDNS discovery. r=xeonchen. (ee3cb0ddb6)
1175 lines
32 KiB
C++
1175 lines
32 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "nsThread.h"
|
|
|
|
#if !defined(MOZILLA_XPCOMRT_API)
|
|
#include "base/message_loop.h"
|
|
#endif // !defined(MOZILLA_XPCOMRT_API)
|
|
|
|
// Chromium's logging can sometimes leak through...
|
|
#ifdef LOG
|
|
#undef LOG
|
|
#endif
|
|
|
|
#include "mozilla/ReentrantMonitor.h"
|
|
#include "nsMemoryPressure.h"
|
|
#include "nsThreadManager.h"
|
|
#include "nsIClassInfoImpl.h"
|
|
#include "nsAutoPtr.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsQueryObject.h"
|
|
#include "pratom.h"
|
|
#include "mozilla/CycleCollectedJSRuntime.h"
|
|
#include "mozilla/Logging.h"
|
|
#include "nsIObserverService.h"
|
|
#if !defined(MOZILLA_XPCOMRT_API)
|
|
#include "mozilla/HangMonitor.h"
|
|
#include "mozilla/IOInterposer.h"
|
|
#include "mozilla/ipc/MessageChannel.h"
|
|
#include "mozilla/ipc/BackgroundChild.h"
|
|
#endif // defined(MOZILLA_XPCOMRT_API)
|
|
#include "mozilla/Services.h"
|
|
#include "nsXPCOMPrivate.h"
|
|
#include "mozilla/ChaosMode.h"
|
|
#include "mozilla/TimeStamp.h"
|
|
|
|
#ifdef MOZ_CRASHREPORTER
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "nsICrashReporter.h"
|
|
#endif
|
|
|
|
#ifdef MOZ_NUWA_PROCESS
|
|
#include "private/pprthred.h"
|
|
#endif
|
|
|
|
#ifdef XP_LINUX
|
|
#include <sys/time.h>
|
|
#include <sys/resource.h>
|
|
#include <sched.h>
|
|
#endif
|
|
|
|
#define HAVE_UALARM _BSD_SOURCE || (_XOPEN_SOURCE >= 500 || \
|
|
_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \
|
|
!(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
|
|
|
|
#if defined(XP_LINUX) && !defined(ANDROID) && defined(_GNU_SOURCE)
|
|
#define HAVE_SCHED_SETAFFINITY
|
|
#endif
|
|
|
|
#ifdef MOZ_CANARY
|
|
# include <unistd.h>
|
|
# include <execinfo.h>
|
|
# include <signal.h>
|
|
# include <fcntl.h>
|
|
# include "nsXULAppAPI.h"
|
|
#endif
|
|
|
|
#if defined(NS_FUNCTION_TIMER) && defined(_MSC_VER)
|
|
#include "nsTimerImpl.h"
|
|
#include "mozilla/StackWalk.h"
|
|
#endif
|
|
#ifdef NS_FUNCTION_TIMER
|
|
#include "nsCRT.h"
|
|
#endif
|
|
|
|
#ifdef MOZ_TASK_TRACER
|
|
#include "GeckoTaskTracer.h"
|
|
#include "TracedTaskCommon.h"
|
|
using namespace mozilla::tasktracer;
|
|
#endif
|
|
|
|
using namespace mozilla;
|
|
|
|
static LazyLogModule sThreadLog("nsThread");
|
|
#ifdef LOG
|
|
#undef LOG
|
|
#endif
|
|
#define LOG(args) MOZ_LOG(sThreadLog, mozilla::LogLevel::Debug, args)
|
|
|
|
NS_DECL_CI_INTERFACE_GETTER(nsThread)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Because we do not have our own nsIFactory, we have to implement nsIClassInfo
|
|
// somewhat manually.
|
|
|
|
class nsThreadClassInfo : public nsIClassInfo
|
|
{
|
|
public:
|
|
NS_DECL_ISUPPORTS_INHERITED // no mRefCnt
|
|
NS_DECL_NSICLASSINFO
|
|
|
|
nsThreadClassInfo()
|
|
{
|
|
}
|
|
};
|
|
|
|
NS_IMETHODIMP_(MozExternalRefCountType)
|
|
nsThreadClassInfo::AddRef()
|
|
{
|
|
return 2;
|
|
}
|
|
NS_IMETHODIMP_(MozExternalRefCountType)
|
|
nsThreadClassInfo::Release()
|
|
{
|
|
return 1;
|
|
}
|
|
NS_IMPL_QUERY_INTERFACE(nsThreadClassInfo, nsIClassInfo)
|
|
|
|
NS_IMETHODIMP
|
|
nsThreadClassInfo::GetInterfaces(uint32_t* aCount, nsIID*** aArray)
|
|
{
|
|
return NS_CI_INTERFACE_GETTER_NAME(nsThread)(aCount, aArray);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThreadClassInfo::GetScriptableHelper(nsIXPCScriptable** aResult)
|
|
{
|
|
*aResult = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThreadClassInfo::GetContractID(char** aResult)
|
|
{
|
|
*aResult = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThreadClassInfo::GetClassDescription(char** aResult)
|
|
{
|
|
*aResult = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThreadClassInfo::GetClassID(nsCID** aResult)
|
|
{
|
|
*aResult = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThreadClassInfo::GetFlags(uint32_t* aResult)
|
|
{
|
|
*aResult = THREADSAFE;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThreadClassInfo::GetClassIDNoAlloc(nsCID* aResult)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMPL_ADDREF(nsThread)
|
|
NS_IMPL_RELEASE(nsThread)
|
|
NS_INTERFACE_MAP_BEGIN(nsThread)
|
|
NS_INTERFACE_MAP_ENTRY(nsIThread)
|
|
NS_INTERFACE_MAP_ENTRY(nsIThreadInternal)
|
|
NS_INTERFACE_MAP_ENTRY(nsIEventTarget)
|
|
NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIThread)
|
|
if (aIID.Equals(NS_GET_IID(nsIClassInfo))) {
|
|
static nsThreadClassInfo sThreadClassInfo;
|
|
foundInterface = static_cast<nsIClassInfo*>(&sThreadClassInfo);
|
|
} else
|
|
NS_INTERFACE_MAP_END
|
|
NS_IMPL_CI_INTERFACE_GETTER(nsThread, nsIThread, nsIThreadInternal,
|
|
nsIEventTarget, nsISupportsPriority)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
class nsThreadStartupEvent : public nsRunnable
|
|
{
|
|
public:
|
|
nsThreadStartupEvent()
|
|
: mMon("nsThreadStartupEvent.mMon")
|
|
, mInitialized(false)
|
|
{
|
|
}
|
|
|
|
// This method does not return until the thread startup object is in the
|
|
// completion state.
|
|
void Wait()
|
|
{
|
|
if (mInitialized) {
|
|
// Maybe avoid locking...
|
|
return;
|
|
}
|
|
|
|
ReentrantMonitorAutoEnter mon(mMon);
|
|
while (!mInitialized) {
|
|
mon.Wait();
|
|
}
|
|
}
|
|
|
|
// This method needs to be public to support older compilers (xlC_r on AIX).
|
|
// It should be called directly as this class type is reference counted.
|
|
virtual ~nsThreadStartupEvent() {}
|
|
|
|
private:
|
|
NS_IMETHOD Run()
|
|
{
|
|
ReentrantMonitorAutoEnter mon(mMon);
|
|
mInitialized = true;
|
|
mon.Notify();
|
|
return NS_OK;
|
|
}
|
|
|
|
ReentrantMonitor mMon;
|
|
bool mInitialized;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
struct nsThreadShutdownContext
|
|
{
|
|
// NB: This will be the last reference.
|
|
RefPtr<nsThread> terminatingThread;
|
|
nsThread* joiningThread;
|
|
bool awaitingShutdownAck;
|
|
};
|
|
|
|
// This event is responsible for notifying nsThread::Shutdown that it is time
|
|
// to call PR_JoinThread. It implements nsICancelableRunnable so that it can
|
|
// run on a DOM Worker thread (where all events must implement
|
|
// nsICancelableRunnable.)
|
|
class nsThreadShutdownAckEvent : public nsRunnable,
|
|
public nsICancelableRunnable
|
|
{
|
|
public:
|
|
explicit nsThreadShutdownAckEvent(nsThreadShutdownContext* aCtx)
|
|
: mShutdownContext(aCtx)
|
|
{
|
|
}
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
NS_IMETHOD Run() override
|
|
{
|
|
mShutdownContext->terminatingThread->ShutdownComplete(mShutdownContext);
|
|
return NS_OK;
|
|
}
|
|
NS_IMETHOD Cancel() override
|
|
{
|
|
return Run();
|
|
}
|
|
private:
|
|
virtual ~nsThreadShutdownAckEvent() { }
|
|
|
|
nsThreadShutdownContext* mShutdownContext;
|
|
};
|
|
|
|
NS_IMPL_ISUPPORTS_INHERITED(nsThreadShutdownAckEvent, nsRunnable,
|
|
nsICancelableRunnable)
|
|
|
|
// This event is responsible for setting mShutdownContext
|
|
class nsThreadShutdownEvent : public nsRunnable
|
|
{
|
|
public:
|
|
nsThreadShutdownEvent(nsThread* aThr, nsThreadShutdownContext* aCtx)
|
|
: mThread(aThr)
|
|
, mShutdownContext(aCtx)
|
|
{
|
|
}
|
|
NS_IMETHOD Run()
|
|
{
|
|
mThread->mShutdownContext = mShutdownContext;
|
|
#if !defined(MOZILLA_XPCOMRT_API)
|
|
MessageLoop::current()->Quit();
|
|
#endif // !defined(MOZILLA_XPCOMRT_API)
|
|
return NS_OK;
|
|
}
|
|
private:
|
|
RefPtr<nsThread> mThread;
|
|
nsThreadShutdownContext* mShutdownContext;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
static void
|
|
SetupCurrentThreadForChaosMode()
|
|
{
|
|
if (!ChaosMode::isActive(ChaosFeature::ThreadScheduling)) {
|
|
return;
|
|
}
|
|
|
|
#ifdef XP_LINUX
|
|
// PR_SetThreadPriority doesn't really work since priorities >
|
|
// PR_PRIORITY_NORMAL can't be set by non-root users. Instead we'll just use
|
|
// setpriority(2) to set random 'nice values'. In regular Linux this is only
|
|
// a dynamic adjustment so it still doesn't really do what we want, but tools
|
|
// like 'rr' can be more aggressive about honoring these values.
|
|
// Some of these calls may fail due to trying to lower the priority
|
|
// (e.g. something may have already called setpriority() for this thread).
|
|
// This makes it hard to have non-main threads with higher priority than the
|
|
// main thread, but that's hard to fix. Tools like rr can choose to honor the
|
|
// requested values anyway.
|
|
// Use just 4 priorities so there's a reasonable chance of any two threads
|
|
// having equal priority.
|
|
setpriority(PRIO_PROCESS, 0, ChaosMode::randomUint32LessThan(4));
|
|
#else
|
|
// We should set the affinity here but NSPR doesn't provide a way to expose it.
|
|
uint32_t priority = ChaosMode::randomUint32LessThan(PR_PRIORITY_LAST + 1);
|
|
PR_SetThreadPriority(PR_GetCurrentThread(), PRThreadPriority(priority));
|
|
#endif
|
|
|
|
#ifdef HAVE_SCHED_SETAFFINITY
|
|
// Force half the threads to CPU 0 so they compete for CPU
|
|
if (ChaosMode::randomUint32LessThan(2)) {
|
|
cpu_set_t cpus;
|
|
CPU_ZERO(&cpus);
|
|
CPU_SET(0, &cpus);
|
|
sched_setaffinity(0, sizeof(cpus), &cpus);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*static*/ void
|
|
nsThread::ThreadFunc(void* aArg)
|
|
{
|
|
#if !defined(MOZILLA_XPCOMRT_API)
|
|
using mozilla::ipc::BackgroundChild;
|
|
#endif // !defined(MOZILLA_XPCOMRT_API)
|
|
|
|
nsThread* self = static_cast<nsThread*>(aArg); // strong reference
|
|
self->mThread = PR_GetCurrentThread();
|
|
SetupCurrentThreadForChaosMode();
|
|
|
|
// Inform the ThreadManager
|
|
nsThreadManager::get()->RegisterCurrentThread(self);
|
|
|
|
#if !defined(MOZILLA_XPCOMRT_API)
|
|
mozilla::IOInterposer::RegisterCurrentThread();
|
|
#endif // !defined(MOZILLA_XPCOMRT_API)
|
|
|
|
// Wait for and process startup event
|
|
nsCOMPtr<nsIRunnable> event;
|
|
{
|
|
MutexAutoLock lock(self->mLock);
|
|
if (!self->mEvents->GetEvent(true, getter_AddRefs(event), lock)) {
|
|
NS_WARNING("failed waiting for thread startup event");
|
|
return;
|
|
}
|
|
}
|
|
event->Run(); // unblocks nsThread::Init
|
|
event = nullptr;
|
|
|
|
{
|
|
#if defined(MOZILLA_XPCOMRT_API)
|
|
while(!self->mShutdownContext) {
|
|
NS_ProcessNextEvent();
|
|
}
|
|
#else
|
|
// Scope for MessageLoop.
|
|
nsAutoPtr<MessageLoop> loop(
|
|
new MessageLoop(MessageLoop::TYPE_MOZILLA_NONMAINTHREAD));
|
|
|
|
// Now, process incoming events...
|
|
loop->Run();
|
|
|
|
BackgroundChild::CloseForCurrentThread();
|
|
#endif // defined(MOZILLA_XPCOMRT_API)
|
|
|
|
// Do NS_ProcessPendingEvents but with special handling to set
|
|
// mEventsAreDoomed atomically with the removal of the last event. The key
|
|
// invariant here is that we will never permit PutEvent to succeed if the
|
|
// event would be left in the queue after our final call to
|
|
// NS_ProcessPendingEvents. We also have to keep processing events as long
|
|
// as we have outstanding mRequestedShutdownContexts.
|
|
while (true) {
|
|
// Check and see if we're waiting on any threads.
|
|
while (self->mRequestedShutdownContexts.Length()) {
|
|
// We can't stop accepting events just yet. Block and check again.
|
|
NS_ProcessNextEvent(self, true);
|
|
}
|
|
|
|
{
|
|
MutexAutoLock lock(self->mLock);
|
|
if (!self->mEvents->HasPendingEvent(lock)) {
|
|
// No events in the queue, so we will stop now. Don't let any more
|
|
// events be added, since they won't be processed. It is critical
|
|
// that no PutEvent can occur between testing that the event queue is
|
|
// empty and setting mEventsAreDoomed!
|
|
self->mEventsAreDoomed = true;
|
|
break;
|
|
}
|
|
}
|
|
NS_ProcessPendingEvents(self);
|
|
}
|
|
}
|
|
|
|
#if !defined(MOZILLA_XPCOMRT_API)
|
|
mozilla::IOInterposer::UnregisterCurrentThread();
|
|
#endif // !defined(MOZILLA_XPCOMRT_API)
|
|
|
|
// Inform the threadmanager that this thread is going away
|
|
nsThreadManager::get()->UnregisterCurrentThread(self);
|
|
|
|
// Dispatch shutdown ACK
|
|
MOZ_ASSERT(self->mShutdownContext->terminatingThread == self);
|
|
event = do_QueryObject(new nsThreadShutdownAckEvent(self->mShutdownContext));
|
|
self->mShutdownContext->joiningThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
|
|
|
// Release any observer of the thread here.
|
|
self->SetObserver(nullptr);
|
|
|
|
#ifdef MOZ_TASK_TRACER
|
|
FreeTraceInfo();
|
|
#endif
|
|
|
|
NS_RELEASE(self);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifdef MOZ_CANARY
|
|
int sCanaryOutputFD = -1;
|
|
#endif
|
|
|
|
nsThread::nsThread(MainThreadFlag aMainThread, uint32_t aStackSize)
|
|
: mLock("nsThread.mLock")
|
|
, mScriptObserver(nullptr)
|
|
, mEvents(&mEventsRoot)
|
|
, mEventsRoot(mLock)
|
|
, mPriority(PRIORITY_NORMAL)
|
|
, mThread(nullptr)
|
|
, mNestedEventLoopDepth(0)
|
|
, mStackSize(aStackSize)
|
|
, mShutdownContext(nullptr)
|
|
, mShutdownRequired(false)
|
|
, mEventsAreDoomed(false)
|
|
, mIsMainThread(aMainThread)
|
|
{
|
|
}
|
|
|
|
nsThread::~nsThread()
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
nsThread::Init()
|
|
{
|
|
// spawn thread and wait until it is fully setup
|
|
RefPtr<nsThreadStartupEvent> startup = new nsThreadStartupEvent();
|
|
|
|
NS_ADDREF_THIS();
|
|
|
|
mShutdownRequired = true;
|
|
|
|
// ThreadFunc is responsible for setting mThread
|
|
PRThread* thr = PR_CreateThread(PR_USER_THREAD, ThreadFunc, this,
|
|
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD,
|
|
PR_JOINABLE_THREAD, mStackSize);
|
|
if (!thr) {
|
|
NS_RELEASE_THIS();
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
// ThreadFunc will wait for this event to be run before it tries to access
|
|
// mThread. By delaying insertion of this event into the queue, we ensure
|
|
// that mThread is set properly.
|
|
{
|
|
MutexAutoLock lock(mLock);
|
|
mEventsRoot.PutEvent(startup, lock); // retain a reference
|
|
}
|
|
|
|
// Wait for thread to call ThreadManager::SetupCurrentThread, which completes
|
|
// initialization of ThreadFunc.
|
|
startup->Wait();
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsThread::InitCurrentThread()
|
|
{
|
|
mThread = PR_GetCurrentThread();
|
|
SetupCurrentThreadForChaosMode();
|
|
|
|
nsThreadManager::get()->RegisterCurrentThread(this);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsThread::PutEvent(nsIRunnable* aEvent, nsNestedEventTarget* aTarget)
|
|
{
|
|
nsCOMPtr<nsIRunnable> event(aEvent);
|
|
return PutEvent(event.forget(), aTarget);
|
|
}
|
|
|
|
nsresult
|
|
nsThread::PutEvent(already_AddRefed<nsIRunnable>&& aEvent, nsNestedEventTarget* aTarget)
|
|
{
|
|
nsCOMPtr<nsIThreadObserver> obs;
|
|
|
|
#ifdef MOZ_NUWA_PROCESS
|
|
// On debug build or when tests are enabled, assert that we are not about to
|
|
// create a deadlock in the Nuwa process.
|
|
NuwaAssertNotFrozen(PR_GetThreadID(mThread), PR_GetThreadName(mThread));
|
|
#endif
|
|
|
|
{
|
|
MutexAutoLock lock(mLock);
|
|
nsChainedEventQueue* queue = aTarget ? aTarget->mQueue : &mEventsRoot;
|
|
if (!queue || (queue == &mEventsRoot && mEventsAreDoomed)) {
|
|
NS_WARNING("An event was posted to a thread that will never run it (rejected)");
|
|
nsCOMPtr<nsIRunnable> temp(aEvent);
|
|
nsIRunnable* temp2 = temp.forget().take(); // can't use unused << aEvent here due to Windows (boo)
|
|
return temp2 ? NS_ERROR_UNEXPECTED : NS_ERROR_UNEXPECTED; // to make compiler not bletch on us
|
|
}
|
|
queue->PutEvent(Move(aEvent), lock);
|
|
|
|
// Make sure to grab the observer before dropping the lock, otherwise the
|
|
// event that we just placed into the queue could run and eventually delete
|
|
// this nsThread before the calling thread is scheduled again. We would then
|
|
// crash while trying to access a dead nsThread.
|
|
obs = mObserver;
|
|
}
|
|
|
|
if (obs) {
|
|
obs->OnDispatchedEvent(this);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsThread::DispatchInternal(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aFlags,
|
|
nsNestedEventTarget* aTarget)
|
|
{
|
|
nsCOMPtr<nsIRunnable> event(aEvent);
|
|
if (NS_WARN_IF(!event)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
if (gXPCOMThreadsShutDown && MAIN_THREAD != mIsMainThread && !aTarget) {
|
|
NS_ASSERTION(false, "Failed Dispatch after xpcom-shutdown-threads");
|
|
return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
|
|
}
|
|
|
|
#ifdef MOZ_TASK_TRACER
|
|
nsCOMPtr<nsIRunnable> tracedRunnable = CreateTracedRunnable(event); // adds a ref
|
|
(static_cast<TracedRunnable*>(tracedRunnable.get()))->DispatchTask();
|
|
event = tracedRunnable.forget();
|
|
#endif
|
|
|
|
if (aFlags & DISPATCH_SYNC) {
|
|
nsThread* thread = nsThreadManager::get()->GetCurrentThread();
|
|
if (NS_WARN_IF(!thread)) {
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
// XXX we should be able to do something better here... we should
|
|
// be able to monitor the slot occupied by this event and use
|
|
// that to tell us when the event has been processed.
|
|
|
|
RefPtr<nsThreadSyncDispatch> wrapper =
|
|
new nsThreadSyncDispatch(thread, event.forget());
|
|
nsresult rv = PutEvent(wrapper, aTarget); // hold a ref
|
|
// Don't wait for the event to finish if we didn't dispatch it...
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
// Allows waiting; ensure no locks are held that would deadlock us!
|
|
while (wrapper->IsPending()) {
|
|
NS_ProcessNextEvent(thread, true);
|
|
}
|
|
return wrapper->Result();
|
|
}
|
|
|
|
NS_ASSERTION(aFlags == NS_DISPATCH_NORMAL, "unexpected dispatch flags");
|
|
return PutEvent(event.forget(), aTarget);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// nsIEventTarget
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
|
|
{
|
|
nsCOMPtr<nsIRunnable> event(aEvent);
|
|
return Dispatch(event.forget(), aFlags);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::Dispatch(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aFlags)
|
|
{
|
|
LOG(("THRD(%p) Dispatch [%p %x]\n", this, /* XXX aEvent */nullptr, aFlags));
|
|
|
|
return DispatchInternal(Move(aEvent), aFlags, nullptr);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::IsOnCurrentThread(bool* aResult)
|
|
{
|
|
*aResult = (PR_GetCurrentThread() == mThread);
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// nsIThread
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::GetPRThread(PRThread** aResult)
|
|
{
|
|
*aResult = mThread;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::AsyncShutdown()
|
|
{
|
|
LOG(("THRD(%p) async shutdown\n", this));
|
|
|
|
// XXX If we make this warn, then we hit that warning at xpcom shutdown while
|
|
// shutting down a thread in a thread pool. That happens b/c the thread
|
|
// in the thread pool is already shutdown by the thread manager.
|
|
if (!mThread) {
|
|
return NS_OK;
|
|
}
|
|
|
|
return !!ShutdownInternal(/* aSync = */ false) ? NS_OK : NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
nsThreadShutdownContext*
|
|
nsThread::ShutdownInternal(bool aSync)
|
|
{
|
|
MOZ_ASSERT(mThread);
|
|
|
|
if (NS_WARN_IF(mThread == PR_GetCurrentThread())) {
|
|
return nullptr;
|
|
}
|
|
|
|
// Prevent multiple calls to this method
|
|
{
|
|
MutexAutoLock lock(mLock);
|
|
if (!mShutdownRequired) {
|
|
return nullptr;
|
|
}
|
|
mShutdownRequired = false;
|
|
}
|
|
|
|
nsThread* currentThread = nsThreadManager::get()->GetCurrentThread();
|
|
MOZ_ASSERT(currentThread);
|
|
|
|
nsAutoPtr<nsThreadShutdownContext>& context =
|
|
*currentThread->mRequestedShutdownContexts.AppendElement();
|
|
context = new nsThreadShutdownContext();
|
|
|
|
context->terminatingThread = this;
|
|
context->joiningThread = currentThread;
|
|
context->awaitingShutdownAck = aSync;
|
|
|
|
// Set mShutdownContext and wake up the thread in case it is waiting for
|
|
// events to process.
|
|
nsCOMPtr<nsIRunnable> event = new nsThreadShutdownEvent(this, context);
|
|
// XXXroc What if posting the event fails due to OOM?
|
|
PutEvent(event.forget(), nullptr);
|
|
|
|
// We could still end up with other events being added after the shutdown
|
|
// task, but that's okay because we process pending events in ThreadFunc
|
|
// after setting mShutdownContext just before exiting.
|
|
return context;
|
|
}
|
|
|
|
void
|
|
nsThread::ShutdownComplete(nsThreadShutdownContext* aContext)
|
|
{
|
|
MOZ_ASSERT(mThread);
|
|
MOZ_ASSERT(aContext->terminatingThread == this);
|
|
|
|
if (aContext->awaitingShutdownAck) {
|
|
// We're in a synchronous shutdown, so tell whatever is up the stack that
|
|
// we're done and unwind the stack so it can call us again.
|
|
aContext->awaitingShutdownAck = false;
|
|
return;
|
|
}
|
|
|
|
// Now, it should be safe to join without fear of dead-locking.
|
|
|
|
PR_JoinThread(mThread);
|
|
mThread = nullptr;
|
|
|
|
// We hold strong references to our event observers, and once the thread is
|
|
// shut down the observers can't easily unregister themselves. Do it here
|
|
// to avoid leaking.
|
|
ClearObservers();
|
|
|
|
#ifdef DEBUG
|
|
{
|
|
MutexAutoLock lock(mLock);
|
|
MOZ_ASSERT(!mObserver, "Should have been cleared at shutdown!");
|
|
}
|
|
#endif
|
|
|
|
// Delete aContext.
|
|
MOZ_ALWAYS_TRUE(
|
|
aContext->joiningThread->mRequestedShutdownContexts.RemoveElement(aContext));
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::Shutdown()
|
|
{
|
|
LOG(("THRD(%p) sync shutdown\n", this));
|
|
|
|
// XXX If we make this warn, then we hit that warning at xpcom shutdown while
|
|
// shutting down a thread in a thread pool. That happens b/c the thread
|
|
// in the thread pool is already shutdown by the thread manager.
|
|
if (!mThread) {
|
|
return NS_OK;
|
|
}
|
|
|
|
nsThreadShutdownContext* context = ShutdownInternal(/* aSync = */ true);
|
|
NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
|
|
|
|
// Process events on the current thread until we receive a shutdown ACK.
|
|
// Allows waiting; ensure no locks are held that would deadlock us!
|
|
while (context->awaitingShutdownAck) {
|
|
NS_ProcessNextEvent(context->joiningThread, true);
|
|
}
|
|
|
|
ShutdownComplete(context);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::HasPendingEvents(bool* aResult)
|
|
{
|
|
if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
|
|
return NS_ERROR_NOT_SAME_THREAD;
|
|
}
|
|
|
|
{
|
|
MutexAutoLock lock(mLock);
|
|
*aResult = mEvents->HasPendingEvent(lock);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
#ifdef MOZ_CANARY
|
|
void canary_alarm_handler(int signum);
|
|
|
|
class Canary
|
|
{
|
|
//XXX ToDo: support nested loops
|
|
public:
|
|
Canary()
|
|
{
|
|
if (sCanaryOutputFD > 0 && EventLatencyIsImportant()) {
|
|
signal(SIGALRM, canary_alarm_handler);
|
|
ualarm(15000, 0);
|
|
}
|
|
}
|
|
|
|
~Canary()
|
|
{
|
|
if (sCanaryOutputFD != 0 && EventLatencyIsImportant()) {
|
|
ualarm(0, 0);
|
|
}
|
|
}
|
|
|
|
static bool EventLatencyIsImportant()
|
|
{
|
|
return NS_IsMainThread() && XRE_IsParentProcess();
|
|
}
|
|
};
|
|
|
|
void canary_alarm_handler(int signum)
|
|
{
|
|
void* array[30];
|
|
const char msg[29] = "event took too long to run:\n";
|
|
// use write to be safe in the signal handler
|
|
write(sCanaryOutputFD, msg, sizeof(msg));
|
|
backtrace_symbols_fd(array, backtrace(array, 30), sCanaryOutputFD);
|
|
}
|
|
|
|
#endif
|
|
|
|
#define NOTIFY_EVENT_OBSERVERS(func_, params_) \
|
|
PR_BEGIN_MACRO \
|
|
if (!mEventObservers.IsEmpty()) { \
|
|
nsAutoTObserverArray<nsCOMPtr<nsIThreadObserver>, 2>::ForwardIterator \
|
|
iter_(mEventObservers); \
|
|
nsCOMPtr<nsIThreadObserver> obs_; \
|
|
while (iter_.HasMore()) { \
|
|
obs_ = iter_.GetNext(); \
|
|
obs_ -> func_ params_ ; \
|
|
} \
|
|
} \
|
|
PR_END_MACRO
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::ProcessNextEvent(bool aMayWait, bool* aResult)
|
|
{
|
|
LOG(("THRD(%p) ProcessNextEvent [%u %u]\n", this, aMayWait,
|
|
mNestedEventLoopDepth));
|
|
|
|
#if !defined(MOZILLA_XPCOMRT_API)
|
|
// If we're on the main thread, we shouldn't be dispatching CPOWs.
|
|
if (mIsMainThread == MAIN_THREAD) {
|
|
ipc::CancelCPOWs();
|
|
}
|
|
#endif // !defined(MOZILLA_XPCOMRT_API)
|
|
|
|
if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
|
|
return NS_ERROR_NOT_SAME_THREAD;
|
|
}
|
|
|
|
// The toplevel event loop normally blocks waiting for the next event, but
|
|
// if we're trying to shut this thread down, we must exit the event loop when
|
|
// the event queue is empty.
|
|
// This only applys to the toplevel event loop! Nested event loops (e.g.
|
|
// during sync dispatch) are waiting for some state change and must be able
|
|
// to block even if something has requested shutdown of the thread. Otherwise
|
|
// we'll just busywait as we endlessly look for an event, fail to find one,
|
|
// and repeat the nested event loop since its state change hasn't happened yet.
|
|
bool reallyWait = aMayWait && (mNestedEventLoopDepth > 0 || !ShuttingDown());
|
|
|
|
#if !defined(MOZILLA_XPCOMRT_API)
|
|
if (MAIN_THREAD == mIsMainThread && reallyWait) {
|
|
HangMonitor::Suspend();
|
|
}
|
|
#endif // !defined(MOZILLA_XPCOMRT_API)
|
|
|
|
// Fire a memory pressure notification, if we're the main thread and one is
|
|
// pending.
|
|
if (MAIN_THREAD == mIsMainThread && !ShuttingDown()) {
|
|
MemoryPressureState mpPending = NS_GetPendingMemoryPressure();
|
|
if (mpPending != MemPressure_None) {
|
|
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
|
|
|
// Use no-forward to prevent the notifications from being transferred to
|
|
// the children of this process.
|
|
NS_NAMED_LITERAL_STRING(lowMem, "low-memory-no-forward");
|
|
NS_NAMED_LITERAL_STRING(lowMemOngoing, "low-memory-ongoing-no-forward");
|
|
|
|
if (os) {
|
|
os->NotifyObservers(nullptr, "memory-pressure",
|
|
mpPending == MemPressure_New ? lowMem.get() :
|
|
lowMemOngoing.get());
|
|
} else {
|
|
NS_WARNING("Can't get observer service!");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef MOZ_CRASHREPORTER
|
|
if (MAIN_THREAD == mIsMainThread && !ShuttingDown()) {
|
|
// Keep an eye on memory usage (cheap, ~7ms) somewhat frequently,
|
|
// but save memory reports (expensive, ~75ms) less frequently.
|
|
const size_t LOW_MEMORY_CHECK_SECONDS = 30;
|
|
const size_t LOW_MEMORY_SAVE_SECONDS = 3 * 60;
|
|
|
|
static TimeStamp nextCheck = TimeStamp::NowLoRes()
|
|
+ TimeDuration::FromSeconds(LOW_MEMORY_CHECK_SECONDS);
|
|
|
|
TimeStamp now = TimeStamp::NowLoRes();
|
|
if (now >= nextCheck) {
|
|
if (SaveMemoryReportNearOOM()) {
|
|
nextCheck = now + TimeDuration::FromSeconds(LOW_MEMORY_SAVE_SECONDS);
|
|
} else {
|
|
nextCheck = now + TimeDuration::FromSeconds(LOW_MEMORY_CHECK_SECONDS);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
++mNestedEventLoopDepth;
|
|
|
|
bool callScriptObserver = !!mScriptObserver;
|
|
if (callScriptObserver) {
|
|
mScriptObserver->BeforeProcessTask(reallyWait);
|
|
}
|
|
|
|
nsCOMPtr<nsIThreadObserver> obs = mObserver;
|
|
if (obs) {
|
|
obs->OnProcessNextEvent(this, reallyWait);
|
|
}
|
|
|
|
NOTIFY_EVENT_OBSERVERS(OnProcessNextEvent, (this, reallyWait));
|
|
|
|
#ifdef MOZ_CANARY
|
|
Canary canary;
|
|
#endif
|
|
nsresult rv = NS_OK;
|
|
|
|
{
|
|
// Scope for |event| to make sure that its destructor fires while
|
|
// mNestedEventLoopDepth has been incremented, since that destructor can
|
|
// also do work.
|
|
|
|
// If we are shutting down, then do not wait for new events.
|
|
nsCOMPtr<nsIRunnable> event;
|
|
{
|
|
MutexAutoLock lock(mLock);
|
|
mEvents->GetEvent(reallyWait, getter_AddRefs(event), lock);
|
|
}
|
|
|
|
*aResult = (event.get() != nullptr);
|
|
|
|
if (event) {
|
|
LOG(("THRD(%p) running [%p]\n", this, event.get()));
|
|
#if !defined(MOZILLA_XPCOMRT_API)
|
|
if (MAIN_THREAD == mIsMainThread) {
|
|
HangMonitor::NotifyActivity();
|
|
}
|
|
#endif // !defined(MOZILLA_XPCOMRT_API)
|
|
event->Run();
|
|
} else if (aMayWait) {
|
|
MOZ_ASSERT(ShuttingDown(),
|
|
"This should only happen when shutting down");
|
|
rv = NS_ERROR_UNEXPECTED;
|
|
}
|
|
}
|
|
|
|
NOTIFY_EVENT_OBSERVERS(AfterProcessNextEvent, (this, *aResult));
|
|
|
|
if (obs) {
|
|
obs->AfterProcessNextEvent(this, *aResult);
|
|
}
|
|
|
|
if (callScriptObserver && mScriptObserver) {
|
|
mScriptObserver->AfterProcessTask(mNestedEventLoopDepth);
|
|
}
|
|
|
|
--mNestedEventLoopDepth;
|
|
|
|
return rv;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// nsISupportsPriority
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::GetPriority(int32_t* aPriority)
|
|
{
|
|
*aPriority = mPriority;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::SetPriority(int32_t aPriority)
|
|
{
|
|
if (NS_WARN_IF(!mThread)) {
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
}
|
|
|
|
// NSPR defines the following four thread priorities:
|
|
// PR_PRIORITY_LOW
|
|
// PR_PRIORITY_NORMAL
|
|
// PR_PRIORITY_HIGH
|
|
// PR_PRIORITY_URGENT
|
|
// We map the priority values defined on nsISupportsPriority to these values.
|
|
|
|
mPriority = aPriority;
|
|
|
|
PRThreadPriority pri;
|
|
if (mPriority <= PRIORITY_HIGHEST) {
|
|
pri = PR_PRIORITY_URGENT;
|
|
} else if (mPriority < PRIORITY_NORMAL) {
|
|
pri = PR_PRIORITY_HIGH;
|
|
} else if (mPriority > PRIORITY_NORMAL) {
|
|
pri = PR_PRIORITY_LOW;
|
|
} else {
|
|
pri = PR_PRIORITY_NORMAL;
|
|
}
|
|
// If chaos mode is active, retain the randomly chosen priority
|
|
if (!ChaosMode::isActive(ChaosFeature::ThreadScheduling)) {
|
|
PR_SetThreadPriority(mThread, pri);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::AdjustPriority(int32_t aDelta)
|
|
{
|
|
return SetPriority(mPriority + aDelta);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// nsIThreadInternal
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::GetObserver(nsIThreadObserver** aObs)
|
|
{
|
|
MutexAutoLock lock(mLock);
|
|
NS_IF_ADDREF(*aObs = mObserver);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::SetObserver(nsIThreadObserver* aObs)
|
|
{
|
|
if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
|
|
return NS_ERROR_NOT_SAME_THREAD;
|
|
}
|
|
|
|
MutexAutoLock lock(mLock);
|
|
mObserver = aObs;
|
|
return NS_OK;
|
|
}
|
|
|
|
uint32_t
|
|
nsThread::RecursionDepth() const
|
|
{
|
|
MOZ_ASSERT(PR_GetCurrentThread() == mThread);
|
|
return mNestedEventLoopDepth;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::AddObserver(nsIThreadObserver* aObserver)
|
|
{
|
|
if (NS_WARN_IF(!aObserver)) {
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
|
|
return NS_ERROR_NOT_SAME_THREAD;
|
|
}
|
|
|
|
NS_WARN_IF_FALSE(!mEventObservers.Contains(aObserver),
|
|
"Adding an observer twice!");
|
|
|
|
if (!mEventObservers.AppendElement(aObserver)) {
|
|
NS_WARNING("Out of memory!");
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::RemoveObserver(nsIThreadObserver* aObserver)
|
|
{
|
|
if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
|
|
return NS_ERROR_NOT_SAME_THREAD;
|
|
}
|
|
|
|
if (aObserver && !mEventObservers.RemoveElement(aObserver)) {
|
|
NS_WARNING("Removing an observer that was never added!");
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::PushEventQueue(nsIEventTarget** aResult)
|
|
{
|
|
if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
|
|
return NS_ERROR_NOT_SAME_THREAD;
|
|
}
|
|
|
|
nsChainedEventQueue* queue = new nsChainedEventQueue(mLock);
|
|
queue->mEventTarget = new nsNestedEventTarget(this, queue);
|
|
|
|
{
|
|
MutexAutoLock lock(mLock);
|
|
queue->mNext = mEvents;
|
|
mEvents = queue;
|
|
}
|
|
|
|
NS_ADDREF(*aResult = queue->mEventTarget);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::PopEventQueue(nsIEventTarget* aInnermostTarget)
|
|
{
|
|
if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
|
|
return NS_ERROR_NOT_SAME_THREAD;
|
|
}
|
|
|
|
if (NS_WARN_IF(!aInnermostTarget)) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
// Don't delete or release anything while holding the lock.
|
|
nsAutoPtr<nsChainedEventQueue> queue;
|
|
RefPtr<nsNestedEventTarget> target;
|
|
|
|
{
|
|
MutexAutoLock lock(mLock);
|
|
|
|
// Make sure we're popping the innermost event target.
|
|
if (NS_WARN_IF(mEvents->mEventTarget != aInnermostTarget)) {
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
MOZ_ASSERT(mEvents != &mEventsRoot);
|
|
|
|
queue = mEvents;
|
|
mEvents = mEvents->mNext;
|
|
|
|
nsCOMPtr<nsIRunnable> event;
|
|
while (queue->GetEvent(false, getter_AddRefs(event), lock)) {
|
|
mEvents->PutEvent(event.forget(), lock);
|
|
}
|
|
|
|
// Don't let the event target post any more events.
|
|
queue->mEventTarget.swap(target);
|
|
target->mQueue = nullptr;
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
nsThread::SetScriptObserver(mozilla::CycleCollectedJSRuntime* aScriptObserver)
|
|
{
|
|
if (!aScriptObserver) {
|
|
mScriptObserver = nullptr;
|
|
return;
|
|
}
|
|
|
|
MOZ_ASSERT(!mScriptObserver);
|
|
mScriptObserver = aScriptObserver;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
nsThreadSyncDispatch::Run()
|
|
{
|
|
if (mSyncTask) {
|
|
mResult = mSyncTask->Run();
|
|
mSyncTask = nullptr;
|
|
// unblock the origin thread
|
|
mOrigin->Dispatch(this, NS_DISPATCH_NORMAL);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMPL_ISUPPORTS(nsThread::nsNestedEventTarget, nsIEventTarget)
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::nsNestedEventTarget::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
|
|
{
|
|
nsCOMPtr<nsIRunnable> event(aEvent);
|
|
return Dispatch(event.forget(), aFlags);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::nsNestedEventTarget::Dispatch(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aFlags)
|
|
{
|
|
LOG(("THRD(%p) Dispatch [%p %x] to nested loop %p\n", mThread.get(), /*XXX aEvent*/ nullptr,
|
|
aFlags, this));
|
|
|
|
return mThread->DispatchInternal(Move(aEvent), aFlags, this);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsThread::nsNestedEventTarget::IsOnCurrentThread(bool* aResult)
|
|
{
|
|
return mThread->IsOnCurrentThread(aResult);
|
|
}
|