app verifier srwlock error in blink::InspectorTaskRunner::InspectorTaskRunner |
||
Issue descriptionRunning Chrome canary under app verifier causes an exception in blink::InspectorTaskRunner::InspectorTaskRunner due to an attempt to initialize an SRWLock that was already initialized. Recreated with Version 71.0.3569.0 (or a few days before) (Official Build) canary (64-bit). I had the defaults selected for app verifier. I suspect it's this page that causes the exception: https://www.thedailybeast.com/trump-interrupts-talks-over-female-reporters-to-defend-kavanaugh-at-insane-press-conference If I leave that page up with app verifier, that tab crashes after ~1 minute. If I've managed to get VS attached to the right process, I get the stack trace below. It's unclear from the code where the ConditionVariable is coming from, between the typedefs and inlining and wrapper classes. vrfcore.dll!VerifierStopMessageEx() Unknown vfbasics.dll!AVrfpRtlInitializeSRWLock() Unknown > chrome_child.dll!base::ConditionVariable::ConditionVariable(base::Lock * user_lock) Line 24 C++ chrome_child.dll!blink::InspectorTaskRunner::InspectorTaskRunner(scoped_refptr<base::SingleThreadTaskRunner> isolate_task_runner) Line 28 C++ chrome_child.dll!blink::LocalFrame::LocalFrame(blink::LocalFrameClient * client, blink::Page & page, blink::FrameOwner * owner, blink::InterfaceRegistry * interface_registry) Line 885 C++ chrome_child.dll!blink::LocalFrame::Create(blink::LocalFrameClient * client, blink::Page & page, blink::FrameOwner * owner, blink::InterfaceRegistry * interface_registry) Line 166 C++ chrome_child.dll!blink::WebLocalFrameImpl::InitializeCoreFrame(blink::Page & page, blink::FrameOwner * owner, const WTF::AtomicString & name) Line 1802 C++ chrome_child.dll!blink::WebLocalFrameImpl::CreateChildFrame(const WTF::AtomicString & name, blink::HTMLFrameOwnerElement * owner_element) Line 1861 C++ chrome_child.dll!blink::HTMLFrameOwnerElement::LoadOrRedirectSubframe(const blink::KURL & url, const WTF::AtomicString & frame_name, bool replace_current_item) Line 382 C++ chrome_child.dll!blink::HTMLFrameElementBase::OpenURL(bool replace_current_item) Line 112 C++ chrome_child.dll!blink::ContainerNode::DidInsertNodeVector(const blink::HeapVector<blink::Member<blink::Node>,11> & targets, blink::Node * next, const blink::HeapVector<blink::Member<blink::Node>,11> & post_insertion_notification_targets) Line 347 C++ chrome_child.dll!blink::ContainerNode::AppendChild(blink::Node * new_child, blink::ExceptionState & exception_state) Line 858 C++ chrome_child.dll!blink::V8Node::appendChildMethodCallbackForMainWorld(const v8::FunctionCallbackInfo<v8::Value> & info) Line 928 C++ chrome_child.dll!v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo * handler) Line 141 C++ chrome_child.dll!v8::internal::`anonymous namespace'::HandleApiCallHelper<0>(v8::internal::Isolate * isolate, v8::internal::Handle<v8::internal::HeapObject> function, v8::internal::Handle<v8::internal::HeapObject> new_target, v8::internal::Handle<v8::internal::FunctionTemplateInfo> fun_data, v8::internal::Handle<v8::internal::Object> receiver, v8::internal::BuiltinArguments args) Line 111 C++ chrome_child.dll!v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments args, v8::internal::Isolate * isolate) Line 0 C++ chrome_child.dll!v8::internal::Builtin_HandleApiCall(int args_length, v8::internal::Object * * args_object, v8::internal::Isolate * isolate) Line 127 C++ [External Code]
,
Oct 23
I think that App verifier's detection of multiple initialization is based on maintaining a database of objects that have been initialized, so it shouldn't be vulnerable to false positives. Do you have a crash dump showing the complaint? Attaching that plus a text file containing the debugger spew should be helpful in understanding what is really going on.
,
Oct 23
If it's based on the address of the object that's been initialized, why wouldn't that be vulnerable to false positives, for objects on the heap, as opposed to global vars?
,
Oct 23
If there is a de-initialize function as well as an initialize function then they could maintain the database. Otherwise not. Since InitializeSRWLock doesn't have a corresponding deinitialize function I guess you are right that false positive are unavoidable. That is disappointing. So maybe this is bogus, in which case we need to disable the appropriate check, which then reduces the value of app verifier. Aside: for Application Verifier bugs it is always a good idea to include the output spew as well as the call stack, as that explains exactly what rule has been broken.
,
Oct 23
I'll attach the spew when I get a chance - running app verifier on chrome is the mother of all context switches. Oh, wait, I forgot I put it in a doc: VERIFIER STOP 0000000000000251: pid 0x4CFC: The SRW Lock is already initialized. 00002337E88BE9D0 : SRW Lock 0000000000001D1C : ThreadId of the thread that initialized the SRW lock. 00000273BCD17FD0 : Address of the initialization stack trace. Use dps <address> to see where the SRW lock was initialized. 0000000000000000 : Not used When I ran under windbg, dps <address> claimed the initializing stack trace was exactly the same as the error stack trace. I don't think we need to disable this check if we initialize the member variables like this : condition_(CONDITION_VARIABLE_INIT)
,
Oct 24
Got it. condition variables can be intialized with condition_(CONDITION_VARIABLE_INIT) and srwlock variables can be initialized with srwlock_(SRWLOCK_INIT). It's a bit weird that the error message references SRW lock but the fix is for a condition variable, but ???
,
Oct 25
Right re initializing the vars. I don't know why the error message references SRW locks (something internal in Windows?), but my proposed change seems to fix the problem.
,
Oct 25
The only weird thing is that I cannot reproduce this in a standalone app. I wonder what the difference is? In my test (attached) I have SRWLock and ConditionVariable objects and they call the init functions and the addresses are necessarily reused (the stack ones for sure, the heap ones almost certainly) and with App Verifier enabled I can't trigger the warning. If I could I'd report a bug. Anyway, initializing with CONDITION_VARIABLE_INIT is legitimate, so we might as well, but I wish I knew whether there was something more to the behavior.
,
Oct 26
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/afe862d373bf453c8d5806148ebd1145711ad57c commit afe862d373bf453c8d5806148ebd1145711ad57c Author: David Bienvenu <davidbienvenu@chromium.org> Date: Fri Oct 26 13:14:22 2018 fix app verify exception with condition var Use static initializer for condition_ member var instead of win api call. Bug: 891924 Change-Id: I61860a13f286389cf955a74d8e4b3e5c3d30bbb9 Reviewed-on: https://chromium-review.googlesource.com/c/1299916 Reviewed-by: Jochen Eisinger <jochen@chromium.org> Commit-Queue: David Bienvenu <davidbienvenu@chromium.org> Cr-Commit-Position: refs/heads/master@{#603069} [modify] https://crrev.com/afe862d373bf453c8d5806148ebd1145711ad57c/third_party/blink/renderer/platform/wtf/threading_win.cc
,
Oct 26
This should be fixed - I'll try app verifier with the next canary build.
,
Oct 27
Thanks for the fix. I finally have a repro of App Verifier detecting this. I've included my entire test program below but the one that it triggers on is the ConditionVariable on the heap. Here are the rules as far as I can tell:
1) This error doesn't fire for addresses on the stack.
2) This error doesn't fire if the contents of the CONDITION_VARIABLE are zero
3) This error doesn't fire if the memory has been freed by the heap in-between calls to InitializeConditionVariable
So, this Application Verifier bug should only be hit under normal circumstances if you use a custom heap or otherwise somehow reuse memory without going through HeapFree. It's not totally clear how Chrome was hitting this but I don't *think* it represents a Chrome bug.
Here's my test code:
#include <Windows.h>
#include <iostream>
#include <memory>
class SRWLock {
public:
SRWLock() {
for (int i = 0; i < 100; ++i)
InitializeSRWLock(&lock_);
}
private:
SRWLOCK lock_;
};
class ConditionVariable {
public:
ConditionVariable() {
InitializeConditionVariable(&lock_);
size_t x = 1;
memcpy(&lock_, &x, sizeof(lock_));
InitializeConditionVariable(&lock_);
}
~ConditionVariable() {
}
private:
CONDITION_VARIABLE lock_;
};
int main() {
for (int i = 0; i < 1000; ++i) {
SRWLock s;
ConditionVariable c;
auto p1 = std::make_unique<SRWLock>();
auto p2 = std::make_unique<ConditionVariable>();
}
}
,
Oct 27
Cool, interesting about the HeapFree thing. |
||
►
Sign in to add a comment |
||
Comment 1 by davidbienvenu@chromium.org
, Oct 22