--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
Is your plan to change both browser process and child process semantics?
How do you know we don't have LazyInstances in browser process that rely on doing something useful in their destructor? Have you done any analysis/audit of this?
On Wed, Oct 26, 2016 at 4:43 PM, Alexei Svitkine <asvi...@chromium.org> wrote:Is your plan to change both browser process and child process semantics?Yes. Specifically, I'm planning to remove the OnExit handler from LazyInstance.At first I tried to add "::Leaky" to only LazyInstances that hit the DCHECK when removing RenderThreadImpl::Shutdown, but I've learned that it's not realistic because there're many LazyInstances that hit the DCHECK :/ So I'm proposing making LazyInstances leaky by default.How do you know we don't have LazyInstances in browser process that rely on doing something useful in their destructor? Have you done any analysis/audit of this?Yeah, this is a good point. If there is any LazyInstance that is doing some meaningful thing in its destructor, the proposed change will cause a problem. It's hard to check >1200 LazyInstances in Chromium though.
On Wed, Oct 26, 2016 at 4:43 PM, Alexei Svitkine <asvi...@chromium.org> wrote:Is your plan to change both browser process and child process semantics?Yes. Specifically, I'm planning to remove the OnExit handler from LazyInstance.At first I tried to add "::Leaky" to only LazyInstances that hit the DCHECK when removing RenderThreadImpl::Shutdown, but I've learned that it's not realistic because there're many LazyInstances that hit the DCHECK :/ So I'm proposing making LazyInstances leaky by default.How do you know we don't have LazyInstances in browser process that rely on doing something useful in their destructor? Have you done any analysis/audit of this?Yeah, this is a good point. If there is any LazyInstance that is doing some meaningful thing in its destructor, the proposed change will cause a problem. It's hard to check >1200 LazyInstances in Chromium though.
If you're concerned about the side effect, here is a more complicated but safer option:- In a multi-process mode, just call exit(0) at the beginning of RenderThreadImpl::Shutdown().- In a single-process mode (including browser tests), leak RenderThreadImpl and all LazyInstances. This would not be problematic because it just happens in a single-process mode.
How did you come up with 1200? I can find under 276 non-leaky LazyInstances: https://cs.chromium.org/search/?q=LazyInstance%3C%5B%5E%3E%5D*%3E%5Cs&sq=package:chromium&type=cs That seems auditable.
On Wed, Oct 26, 2016 at 8:47 AM, Kentaro Hara <har...@google.com> wrote:On Wed, Oct 26, 2016 at 4:43 PM, Alexei Svitkine <asvi...@chromium.org> wrote:Is your plan to change both browser process and child process semantics?Yes. Specifically, I'm planning to remove the OnExit handler from LazyInstance.At first I tried to add "::Leaky" to only LazyInstances that hit the DCHECK when removing RenderThreadImpl::Shutdown, but I've learned that it's not realistic because there're many LazyInstances that hit the DCHECK :/ So I'm proposing making LazyInstances leaky by default.How do you know we don't have LazyInstances in browser process that rely on doing something useful in their destructor? Have you done any analysis/audit of this?Yeah, this is a good point. If there is any LazyInstance that is doing some meaningful thing in its destructor, the proposed change will cause a problem. It's hard to check >1200 LazyInstances in Chromium though.This is what worries me, i.e. unintended consequences.The renderer side change is great; if we can do below that seems like it would have less side effects.If you're concerned about the side effect, here is a more complicated but safer option:- In a multi-process mode, just call exit(0) at the beginning of RenderThreadImpl::Shutdown().- In a single-process mode (including browser tests), leak RenderThreadImpl and all LazyInstances. This would not be problematic because it just happens in a single-process mode.THere are only a very small number of browser tests that run in single process mode. We can try writing them in other ways.
(FWIW, I like this direction but it's not obvious to me how you'd make the change and ensure you don't break something subtle.)On Wed, Oct 26, 2016 at 6:34 AM, Kentaro Hara <har...@chromium.org> wrote:--HiTL;DR: I'm planning to make base::LazyInstance Leaky by default. Please let me know if there's any concern about it.[Details]I'm now trying to remove a shutdown sequence (=RenderThreadImpl::Shutdown) from the renderer process. RenderThreadImpl::Shutdown has caused a lot of use-after-free bugs and many engineers have spent lots of time fixing complicated ordering issues around the shutdown. As discussed in blink-dev and platform-architecture-dev, there is no reason we have to shut down the renderer gracefully. It's just causing use-after-free bugs and wasting performance.At first, I tried to simply remove RenderThreadImpl::Shutdown but it broke a lot of things. If we simply remove RenderThreadImpl::Shutdown, we end up with destructing RenderThreadImpl and MessageLoop without stopping worker threads. Then the worker threads crash when they post a task to an already-destructed MessageLoop.Next, I tried to forcibly call exit(0) at the beginning of RenderThreadImpl::Shutdown(). However, this didn't work well in a single-process mode and browser tests because it forcibly exits the process before the browser side is ready to exit.So I'm now trying yet another approach: Don't call RenderThreadImpl::Shutdown() and leak RenderThreadImpl. If we go this way, we need to leak all LazyInstances as well (otherwise we hit an error like this). With that change, I confirmed that the approach passes all tests.As far as I understand, there would be no benefit in destructing LazyInstances when OnExit is called. So I think it would be okay to leak LazyInstances, but if I'm missing something, please let me know.Thanks!--Kentaro Hara, Tokyo, Japan
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
--Kentaro Hara, Tokyo, Japan
Nico:How did you come up with 1200? I can find under 276 non-leaky LazyInstances: https://cs.chromium.org/search/?q=LazyInstance%3C%5B%5E%3E%5D*%3E%5Cs&sq=package:chromium&type=cs That seems auditable.Ah, your query looks correct. Yeah, that seems auditable.On Wed, Oct 26, 2016 at 8:02 PM, John Abd-El-Malek <j...@chromium.org> wrote:On Wed, Oct 26, 2016 at 8:47 AM, Kentaro Hara <har...@google.com> wrote:On Wed, Oct 26, 2016 at 4:43 PM, Alexei Svitkine <asvi...@chromium.org> wrote:Is your plan to change both browser process and child process semantics?Yes. Specifically, I'm planning to remove the OnExit handler from LazyInstance.At first I tried to add "::Leaky" to only LazyInstances that hit the DCHECK when removing RenderThreadImpl::Shutdown, but I've learned that it's not realistic because there're many LazyInstances that hit the DCHECK :/ So I'm proposing making LazyInstances leaky by default.How do you know we don't have LazyInstances in browser process that rely on doing something useful in their destructor? Have you done any analysis/audit of this?Yeah, this is a good point. If there is any LazyInstance that is doing some meaningful thing in its destructor, the proposed change will cause a problem. It's hard to check >1200 LazyInstances in Chromium though.This is what worries me, i.e. unintended consequences.The renderer side change is great; if we can do below that seems like it would have less side effects.If you're concerned about the side effect, here is a more complicated but safer option:- In a multi-process mode, just call exit(0) at the beginning of RenderThreadImpl::Shutdown().- In a single-process mode (including browser tests), leak RenderThreadImpl and all LazyInstances. This would not be problematic because it just happens in a single-process mode.THere are only a very small number of browser tests that run in single process mode. We can try writing them in other ways.However, we still need to support a single-process mode
I prefer early termination (exit(0)) to making everything leaky.
I've been thinking a lot about the browser side equivalence of this and I think we want to keep a clear ownership graph that allows us to wind things down when we want to to make it possible for things like LSAN, unit tests, and single-process mode to still work properly.
Deciding to terminate early in the product is a very different decision and paradigm then intentionally dropping ownership semantics and leaking everything.
Thanks all!So the conclusion is:1) Rewrite a couple of single-process-mode tests to multi-process-mode tests.
2) Simply call exit(0) at the beginning of RenderThreadImpl::Shutdown().
On Thu, 27 Oct 2016 at 10:40 Kentaro Hara <har...@google.com> wrote:Thanks all!So the conclusion is:1) Rewrite a couple of single-process-mode tests to multi-process-mode tests.If that's possible then this seems reasonable.2) Simply call exit(0) at the beginning of RenderThreadImpl::Shutdown().You want to call _exit(), or just SIGKILL the current process; exit() implies various shutdown work on POSIX.
Why do you prefer that? LSAN, unit tests, single-process mode all don't require cleanup of globals.
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev+unsubscribe@chromium.org.
And also, the vast majority of LazyInstances is already Leaky, which suggests that this is a better default. So I think swapping the default and auditing the non-leaky lazy instances sounds like a great change.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev...@chromium.org.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev+unsubscribe@chromium.org.
--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev+unsubscribe@chromium.org.
--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev
---
You received this message because you are subscribed to the Google Groups "Chromium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to chromium-dev+unsubscribe@chromium.org.
Just a few thoughts - but do any of these changes have the potential to play havoc with our sanitiser bots e.g. valgrind, drmemory, or asan leak detectors? How will they handle the base::Process::Terminate()?
On Thu, Oct 27, 2016 at 11:28 PM, Will Harris <w...@chromium.org> wrote:Just a few thoughts - but do any of these changes have the potential to play havoc with our sanitiser bots e.g. valgrind, drmemory, or asan leak detectors? How will they handle the base::Process::Terminate()?Good point.When is valgrind, dmemory and LSan running? Is it before RenderThreadImpl::Shutdown? If it's running after RenderThreadImpl::Shutdown, calling exit(0) will just make those sanitizers useless (which should not be acceptable).
Can you rephrase the questions?What's wrong with lsan+exit(0)?
On Mon, Oct 31, 2016 at 7:38 PM, Kentaro Hara <har...@google.com> wrote:The question is:Will LSan work as expected even when we cal exit(0) at the beginning of RenderThreadImpl::Shutdown()?
Yes, it should.It's easy to verify -- introduce an intentional leak and see what happens:static volatile int *leaky_var; // global...leaky_var = new int;leaky_var = nullptr; // previous value leaked
On Tue, Nov 1, 2016 at 4:46 AM Kostya Serebryany <k...@google.com> wrote:On Mon, Oct 31, 2016 at 7:38 PM, Kentaro Hara <har...@google.com> wrote:The question is:Will LSan work as expected even when we cal exit(0) at the beginning of RenderThreadImpl::Shutdown()?There are two things here:1) IIRC the plan here is eventually to call _exit(0) not exit(0) (discussion here)I think LSan depends on the atexit hook to do its final analysis, which _exit(0) will kill entirely. Unless there is extra magic that hooks LSan differently in our test harness.2) LazyInstance::Leaky has the right ANNOTATE_SCOPED_MEMORY_LEAK which tells LSan to not alert on a given object.I think the question here is: does it also:A) apply recursively to all the objects owned by that?OrB) does the exclusion apply only to the owned objects that have been created in the ctor, but not owned later?I think B.In more practical words, if you have:class RenderThreadImpl {RenderThreadImpl() x(new Something) {}void InitializeLaterY() { y.reset(new SomethingElse); }unique_ptr<..> x;unique_ptr<..> y;}And you make a LazyInstance<RenderThreadImpl>::LeakyAnd later at some point you just exit(0) without destroying.I think LSan will not complain about x but will complain about y.If this is the case, I think this means that if you make RenderThreadImpl ::Leaky, all the smart pointers that have been initialized *after* the RTI ctor will be detected as leaks if you abruptly exit before tearing down RTI.
On Tue, Nov 1, 2016 at 8:14 PM, Primiano Tucci <prim...@chromium.org> wrote:On Tue, Nov 1, 2016 at 4:46 AM Kostya Serebryany <k...@google.com> wrote:On Mon, Oct 31, 2016 at 7:38 PM, Kentaro Hara <har...@google.com> wrote:The question is:Will LSan work as expected even when we cal exit(0) at the beginning of RenderThreadImpl::Shutdown()?There are two things here:1) IIRC the plan here is eventually to call _exit(0) not exit(0) (discussion here)I think LSan depends on the atexit hook to do its final analysis, which _exit(0) will kill entirely. Unless there is extra magic that hooks LSan differently in our test harness.
On Tue, Nov 1, 2016 at 8:20 PM, Kentaro Hara <har...@google.com> wrote:On Tue, Nov 1, 2016 at 8:14 PM, Primiano Tucci <prim...@chromium.org> wrote:On Tue, Nov 1, 2016 at 4:46 AM Kostya Serebryany <k...@google.com> wrote:On Mon, Oct 31, 2016 at 7:38 PM, Kentaro Hara <har...@google.com> wrote:The question is:Will LSan work as expected even when we cal exit(0) at the beginning of RenderThreadImpl::Shutdown()?There are two things here:1) IIRC the plan here is eventually to call _exit(0) not exit(0) (discussion here)I think LSan depends on the atexit hook to do its final analysis, which _exit(0) will kill entirely. Unless there is extra magic that hooks LSan differently in our test harness.I noticed one more thing.If we need to call _exit(0) (by calling base::Process::Terminate), it means not only that LSan doesn't run but also that LeakyInstances are not destructed. Doesn't it mean that we'll anyway need to make all LeakyInstances (at least all LeakyInstances on the renderer process) leaky?
If my understanding is correct, we'll need to make the following changes:1) Make all LeakyInstances leaky.2) Move the LSan verification to the beginning of RenderThreadImpl::Shutdown.3) Call _exit(0) after the LSan verification.
Here is another question: Do we really need to call _exit(0) instead of exit(0)? If we can call exit(0), we can just the current LSan verification and keep LeakyInstances non-leaky.
On Wed, Nov 2, 2016 at 2:16 AM Kentaro Hara <har...@google.com> wrote:On Tue, Nov 1, 2016 at 8:20 PM, Kentaro Hara <har...@google.com> wrote:On Tue, Nov 1, 2016 at 8:14 PM, Primiano Tucci <prim...@chromium.org> wrote:On Tue, Nov 1, 2016 at 4:46 AM Kostya Serebryany <k...@google.com> wrote:On Mon, Oct 31, 2016 at 7:38 PM, Kentaro Hara <har...@google.com> wrote:The question is:Will LSan work as expected even when we cal exit(0) at the beginning of RenderThreadImpl::Shutdown()?There are two things here:1) IIRC the plan here is eventually to call _exit(0) not exit(0) (discussion here)I think LSan depends on the atexit hook to do its final analysis, which _exit(0) will kill entirely. Unless there is extra magic that hooks LSan differently in our test harness.I noticed one more thing.If we need to call _exit(0) (by calling base::Process::Terminate), it means not only that LSan doesn't run but also that LeakyInstances are not destructed. Doesn't it mean that we'll anyway need to make all LeakyInstances (at least all LeakyInstances on the renderer process) leaky?Well calling _exit means that all the LazyInstance-s will be de-facto leaky.At this point it might be conceptually cleaner to make them Leaky to reflect what's really happening.Let me wrap the question around: what is the benefit of triggering the AtExit handlers? Why those non-laky LazyInstance are such?If my understanding is correct, we'll need to make the following changes:1) Make all LeakyInstances leaky.2) Move the LSan verification to the beginning of RenderThreadImpl::Shutdown.3) Call _exit(0) after the LSan verification.Yup this makes sense to me % the fact that I honestly got a bit lost in this thread, and I am not sure what are the concerns against leaky-fying the LazyInstances
Here is another question: Do we really need to call _exit(0) instead of exit(0)? If we can call exit(0), we can just the current LSan verification and keep LeakyInstances non-leaky.My only fear here is that by calling all the non-leaky LazyInstance dtors you might still hit (D)Checks if they make assumptions on each other lifetime and their destruction order violates those assumptions.Which, if I understood correctly, is the original problem you are trying to solve.
--
That SGTM. But I'd like to ponder another potential approach:We could skip _exit(0) #if defined(LEAK_SANITIZER). I was thinking of using this approach for the browser-side of things. That way we disassociate memory management from application lifetime. LSAN ensures that the ownership graph is sane (everything can be and is teared down in a full shutdown), but in the official product we make the decision of terminating the application early (which is orthogonal to memory management).WDYT?
On Thu, Nov 3, 2016 at 12:16 AM, Gabriel Charette <g...@chromium.org> wrote:That SGTM. But I'd like to ponder another potential approach:We could skip _exit(0) #if defined(LEAK_SANITIZER). I was thinking of using this approach for the browser-side of things. That way we disassociate memory management from application lifetime. LSAN ensures that the ownership graph is sane (everything can be and is teared down in a full shutdown), but in the official product we make the decision of terminating the application early (which is orthogonal to memory management).WDYT?What's the point of skipping _exit(0)?I'm assuming you're proposing leaking all LeakyInstances and RenderThreadImpl (annotated with MEMORY_LEAK) and then run LSan at the AtExit hook. However, how is it different from just running LSan before calling _exit(0)?
That SGTM. But I'd like to ponder another potential approach:We could skip _exit(0) #if defined(LEAK_SANITIZER). I was thinking of using this approach for the browser-side of things. That way we disassociate memory management from application lifetime. LSAN ensures that the ownership graph is sane (everything can be and is teared down in a full shutdown), but in the official product we make the decision of terminating the application early (which is orthogonal to memory management).WDYT?
On Wed, Nov 2, 2016 at 11:30 AM 'Kentaro Hara' via Chromium-dev <chromi...@chromium.org> wrote:On Thu, Nov 3, 2016 at 12:16 AM, Gabriel Charette <g...@chromium.org> wrote:That SGTM. But I'd like to ponder another potential approach:We could skip _exit(0) #if defined(LEAK_SANITIZER). I was thinking of using this approach for the browser-side of things. That way we disassociate memory management from application lifetime. LSAN ensures that the ownership graph is sane (everything can be and is teared down in a full shutdown), but in the official product we make the decision of terminating the application early (which is orthogonal to memory management).WDYT?What's the point of skipping _exit(0)?I'm assuming you're proposing leaking all LeakyInstances and RenderThreadImpl (annotated with MEMORY_LEAK) and then run LSan at the AtExit hook. However, how is it different from just running LSan before calling _exit(0)?Running LSan before calling _exit(0) earlier than it currently I expect will require further leak annotations (on non-globals).
Then our plan is like this?1) Rewrite single-process-mode tests to multi-process-mode tests. This is needed to make 2) work in single-process-mode tests.
2) If !#defined(LSAN), call _exit(0) at the beginning of RenderThreadImpl::Shutdown(). Otherwise, leak all LazyInstances and RenderThreadImpl and run LSan at the AtExit hook.
Here we need to add MEMORY_LEAK to all LazyInstances and RenderThreadImpl.
In 2), I'd still prefer just calling LSan before _exit(0) to avoid having different code paths between LSan and !LSan, but let's see if it works.
On Wed, Nov 2, 2016 at 3:37 PM Gabriel Charette <g...@chromium.org> wrote:On Wed, Nov 2, 2016 at 11:30 AM 'Kentaro Hara' via Chromium-dev <chromi...@chromium.org> wrote:On Thu, Nov 3, 2016 at 12:16 AM, Gabriel Charette <g...@chromium.org> wrote:That SGTM. But I'd like to ponder another potential approach:We could skip _exit(0) #if defined(LEAK_SANITIZER). I was thinking of using this approach for the browser-side of things. That way we disassociate memory management from application lifetime. LSAN ensures that the ownership graph is sane (everything can be and is teared down in a full shutdown), but in the official product we make the decision of terminating the application early (which is orthogonal to memory management).WDYT?What's the point of skipping _exit(0)?I'm assuming you're proposing leaking all LeakyInstances and RenderThreadImpl (annotated with MEMORY_LEAK) and then run LSan at the AtExit hook. However, how is it different from just running LSan before calling _exit(0)?Running LSan before calling _exit(0) earlier than it currently I expect will require further leak annotations (on non-globals).Hmm why? It should be the other way round. By running LSan before calling (_)exit(0) we'd end up having a larger retaining graph which whitelists more allocations for LSan checks.
On Wed, Nov 2, 2016 at 3:16 PM Gabriel Charette <g...@chromium.org> wrote:That SGTM. But I'd like to ponder another potential approach:We could skip _exit(0) #if defined(LEAK_SANITIZER). I was thinking of using this approach for the browser-side of things. That way we disassociate memory management from application lifetime. LSAN ensures that the ownership graph is sane (everything can be and is teared down in a full shutdown), but in the official product we make the decision of terminating the application early (which is orthogonal to memory management).WDYT?I think that will create a maintenance unbalance on LSan. Effectively LSan will become the only thing that will still cover the dependencies on destruction order, which is the problem haraken is trying to get rid of.In other words sounds like we are saying "destruction order is causing a lot of headaches for our tests today due to UAF & co. Let's make that a headache only for tests that run under Lsan"
On Wed, Nov 2, 2016 at 11:57 AM Primiano Tucci <prim...@chromium.org> wrote:On Wed, Nov 2, 2016 at 3:37 PM Gabriel Charette <g...@chromium.org> wrote:On Wed, Nov 2, 2016 at 11:30 AM 'Kentaro Hara' via Chromium-dev <chromi...@chromium.org> wrote:On Thu, Nov 3, 2016 at 12:16 AM, Gabriel Charette <g...@chromium.org> wrote:That SGTM. But I'd like to ponder another potential approach:We could skip _exit(0) #if defined(LEAK_SANITIZER). I was thinking of using this approach for the browser-side of things. That way we disassociate memory management from application lifetime. LSAN ensures that the ownership graph is sane (everything can be and is teared down in a full shutdown), but in the official product we make the decision of terminating the application early (which is orthogonal to memory management).WDYT?What's the point of skipping _exit(0)?I'm assuming you're proposing leaking all LeakyInstances and RenderThreadImpl (annotated with MEMORY_LEAK) and then run LSan at the AtExit hook. However, how is it different from just running LSan before calling _exit(0)?Running LSan before calling _exit(0) earlier than it currently I expect will require further leak annotations (on non-globals).Hmm why? It should be the other way round. By running LSan before calling (_)exit(0) we'd end up having a larger retaining graph which whitelists more allocations for LSan checks.Doesn't "retaining graph" == "leak annotations"? i.e. we have to mark more things as "leaks" == "not yet deleted when running the check"?
...
[Message clipped]
Random note: Implementing the idea of "call LSAN function before _exit(0)" sounds like it might be a motivator to use std::[at_]quick_exit(), which is currently in the "TBD" section of the Chromium C++11 style guide. If you think that would be useful for this, I'd send a proposal to the cxx list that we allow this. I doubt there would be any objection.PK
--
Would be nice if leaky objects could still be leaky in tests (because invoking dtors often causes ordering problems that we established we don't care about) but re-created (hence the old instance *actually* leaked) when we start a new test (fixture? Unit?)
I am thinking something on the lines of :
- LazyInstance having a global int g_generation_for_testing
- the Pointer() method having something like: if (this.generation ! = g_generation_for_testing) obj_ = new T() ; (behind #if official so we don't pay the cost of that "if" in official builds)
- the test harness invoking LazyInstance::IncrementGenerationForTesting()
Oh you are right about leaky lazy instances going away. I think Scott himself (or somebody else, I can't remembere) already refactored most of them.
>guess one difference is that LazyInstance will allocate into BSS, while using a function-level static will allocate off the general heap... I'm not sure if that really matters though.
what I see that most leaky instances got translated into: static T* x = new T() so they are heap based anyways. Not sure if there is a good reason to though.
After shess mentioned singletons, I see we have quite a lot of those too, and that they also default to running destructors at process exit, which seems even more questionable.I tried browsing for 30s at head, and there's 382 in the stack of AtExitManager Closure()s. Maybe we ought to be pleasantly surprised we accomplish orderly shutdown in finite time!
It might be a "fun" project to track how long those take to run in the real world (tricky since metrics will be shutting down too), and work on driving that to 0.