Opened 23 months ago

Last modified 5 months ago

#3595 reviewing defect

Get rid of detached threads

Reported by: sergz Assignee:
Priority: P2 Milestone:
Module: Libadblockplus Keywords:
Cc: fhd, rjeschke, oleksandr, eric@…, asmirnov, hfiguiere Blocked By: #4688, #4692, #5179
Blocking: Platform: Unknown / Cross platform
Ready: no Confidential: no
Tester: Unknown Verified working: no
Review URL(s):

https://codereview.adblockplus.org/29367507/
https://codereview.adblockplus.org/29367522/
https://codereview.adblockplus.org/29395640/

Description (last modified by sergz)

adblockplus uses timers (setTimeout) (with very long firing intervals). Current implementation in libadblockplus uses free running timer threads, each thread is represented as an instance of a TimeoutThread class which holds JsValuePtr function; and JsValueList functionArguments; which hold JsEnginePtr jsEngine; that holds isolate.

It results in some race conditions in tests as well as in some memory leakages (see #3593).

What to change

Stop keeping strong references to JsEngine and stop all timers when JsEngine is being destroyed.

Change History (19)

comment:1 Changed 23 months ago by sergz

  • Blocking 3593 added

comment:2 Changed 20 months ago by sergz

  • Description modified (diff)

What do you think about using of libuv for async IO and timers? It should allow us to get rid of detached threads and avoid having of any internal resources longer than the scope of JsEngine among currently supported platforms.

comment:3 Changed 14 months ago by asmirnov

  • Cc Anton added

comment:4 Changed 13 months ago by sergz

  • Blocked By 4688 added

comment:5 Changed 13 months ago by sergz

  • Blocked By 4692 added

comment:6 Changed 12 months ago by eric@…

  • Review URL(s) modified (diff)
  • Status changed from new to reviewing

comment:7 Changed 12 months ago by eric@…

The solution in ​https://codereview.adblockplus.org/29367507/, and continued in ​https://codereview.adblockplus.org/29367522/, is to not detach threads. That means setting up an infrastructure to be able to call join() on them somewhere. What it does not mean for those changes is eliminating the threads entirely. That might be desirable in its own right, but it would be a separate change.

Last edited 12 months ago by eric@… (previous) (diff)

comment:8 Changed 9 months ago by sergz

  • Cc asmirnov added; Anton removed

comment:9 Changed 9 months ago by sergz

  • Review URL(s) modified (diff)

comment:10 Changed 9 months ago by sergz

  • Priority changed from P3 to P2

comment:11 Changed 9 months ago by abpbot

A commit referencing this issue has landed:
Issue 3595 - Get rid of detached threads for setTimeout

comment:12 Changed 9 months ago by sergz

  • Cc hfiguiere added

Just for reference, currently tests crash pretty often after finishing main. I have debugged a bit, it happens mostly from FileSystem threads (they are manipulating backups of patterns.ini) and sometimes from WebRequest threads. The reason of the crash are either different failed asserts in v8 or access violation in v8 (attempts to read already freed memory, e.g. at 0xFEEEFEEE, some members are 0xCDCDCDCD, see Magic debug values ). I would suppose that there are some static variables which are destroyed after main and our threads are trying to access them via v8. These crashes should go away after finishing with this issue.

comment:13 Changed 9 months ago by hfiguiere

Using clang AddressSanitizer should help finding some of the issues.

I run the test with:

make CXXFLAGS="-O1 -fno-optimize-sibling-calls -fsanitize=address -fno-omit-frame-pointer" LDFLAGS=-fsanitize=address test

And it crashed with:

==41589==ERROR: AddressSanitizer: heap-use-after-free on address 0x60600001afc0 at pc 0x000108235bb4 bp 0x70000c7edbf0 sp 0x70000c7edbe8
READ of size 8 at 0x60600001afc0 thread T54
    #0 0x108235bb3 in std::__1::cv_status std::__1::condition_variable::wait_until<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > >(std::__1::unique_lock<std::__1::mutex>&, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&) chrono:778
    #1 0x10829e882 in AdblockPlus::DefaultTimer::ThreadFunc() DefaultTimer.cpp:66
    #2 0x10829f374 in AdblockPlus::DefaultTimer::DefaultTimer()::$_0::operator()() const DefaultTimer.cpp:27
    #3 0x10829f28c in std::__1::__thread_proxy<std::__1::tuple<AdblockPlus::DefaultTimer::DefaultTimer()::$_0> >(void*, void*) __functional_base:416
    #4 0x7fffe2fe09ae in _pthread_body (libsystem_pthread.dylib:x86_64+0x39ae)
    #5 0x7fffe2fe08fa in _pthread_start (libsystem_pthread.dylib:x86_64+0x38fa)
    #6 0x7fffe2fe0100 in thread_start (libsystem_pthread.dylib:x86_64+0x3100)

0x60600001afc0 is located 0 bytes inside of 64-byte region [0x60600001afc0,0x60600001b000)
freed by thread T0 here:
    #0 0x10a023d6b in wrap__ZdlPv (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x60d6b)
    #1 0x1082a00b3 in std::__1::__split_buffer<AdblockPlus::DefaultTimer::TimerUnit, std::__1::allocator<AdblockPlus::DefaultTimer::TimerUnit>&>::~__split_buffer() new:177
    #2 0x10829fd08 in std::__1::__split_buffer<AdblockPlus::DefaultTimer::TimerUnit, std::__1::allocator<AdblockPlus::DefaultTimer::TimerUnit>&>::~__split_buffer() __split_buffer:340
    #3 0x10829f6c6 in void std::__1::vector<AdblockPlus::DefaultTimer::TimerUnit, std::__1::allocator<AdblockPlus::DefaultTimer::TimerUnit> >::__push_back_slow_path<AdblockPlus::DefaultTimer::TimerUnit const&>(AdblockPlus::DefaultTimer::TimerUnit const&&&) vector:1580
    #4 0x10829e4bf in AdblockPlus::DefaultTimer::SetTimer(std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l> > const&, std::__1::function<void ()> const&) vector:1596
    #5 0x1082beaff in AdblockPlus::JsEngine::ScheduleTimer(v8::Arguments const&) JsEngine.cpp:108
    #6 0x1082bd431 in (anonymous namespace)::SetTimeoutCallback(v8::Arguments const&) GlobalJsObject.cpp:40
    #7 0x1083b4cb5 in v8::internal::FunctionCallbackArguments::Call(v8::Handle<v8::Value> (*)(v8::Arguments const&)) arguments.cc:109
    #8 0x108406014 in v8::internal::MaybeObject* v8::internal::HandleApiCallHelper<false>(v8::internal::(anonymous namespace)::BuiltinArguments<(v8::internal::BuiltinExtraArguments)1>, v8::internal::Isolate*) builtins.cc:1272
    #9 0x108405b98 in v8::internal::Builtin_Impl_HandleApiCall(v8::internal::(anonymous namespace)::BuiltinArguments<(v8::internal::BuiltinExtraArguments)1>, v8::internal::Isolate*) builtins.cc:1289
    #10 0x1083f53eb in v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) builtins.cc:1288
    #11 0xf5ea27072cd  (<unknown module>)
    #12 0xf5ea2770daf  (<unknown module>)
    #13 0xf5ea2770c70  (<unknown module>)
    #14 0xf5ea27108f3  (<unknown module>)
    #15 0xf5ea2770855  (<unknown module>)
    #16 0xf5ea272ab36  (<unknown module>)
    #17 0xf5ea2772fac  (<unknown module>)
    #18 0xf5ea2772d1d  (<unknown module>)
    #19 0xf5ea2772e60  (<unknown module>)
    #20 0xf5ea272aee3  (<unknown module>)
    #21 0xf5ea2717e96  (<unknown module>)
    #22 0x108491881 in v8::internal::Invoke(bool, v8::internal::Handle<v8::internal::JSFunction>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*, bool*) execution.cc:119
    #23 0x108490d71 in v8::internal::Execution::Call(v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*, bool*, bool) execution.cc:182
    #24 0x10833dfc5 in v8::Script::Run() api.cc:2039
    #25 0x1082c0bfb in AdblockPlus::JsEngine::Evaluate(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) JsEngine.cpp:163
    #26 0x1082abec0 in AdblockPlus::FilterEngine::CreateAsync(std::__1::shared_ptr<AdblockPlus::JsEngine> const&, std::__1::function<void (std::__1::shared_ptr<AdblockPlus::FilterEngine> const&)> const&, AdblockPlus::FilterEngine::CreationParameters const&) FilterEngine.cpp:204
    #27 0x1082ac4a5 in AdblockPlus::FilterEngine::Create(std::__1::shared_ptr<AdblockPlus::JsEngine> const&, AdblockPlus::FilterEngine::CreationParameters const&) FilterEngine.cpp:212
    #28 0x108231831 in (anonymous namespace)::FilterEngineTestGeneric<LazyFileSystem, AdblockPlus::DefaultLogSystem>::SetUp() FilterEngine.cpp:58
    #29 0x108322861 in testing::Test* testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::TestFactoryBase, testing::Test*>(testing::internal::TestFactoryBase*, testing::Test* (testing::internal::TestFactoryBase::*)(), char const*) gtest.cc:2402

previously allocated by thread T0 here:
    #0 0x10a02376b in wrap__Znwm (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x6076b)
    #1 0x10829fd8c in std::__1::__split_buffer<AdblockPlus::DefaultTimer::TimerUnit, std::__1::allocator<AdblockPlus::DefaultTimer::TimerUnit>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<AdblockPlus::DefaultTimer::TimerUnit>&) new:169
    #2 0x10829fa88 in std::__1::__split_buffer<AdblockPlus::DefaultTimer::TimerUnit, std::__1::allocator<AdblockPlus::DefaultTimer::TimerUnit>&>::__split_buffer(unsigned long, unsigned long, std::__1::allocator<AdblockPlus::DefaultTimer::TimerUnit>&) __split_buffer:310
    #3 0x10829f676 in void std::__1::vector<AdblockPlus::DefaultTimer::TimerUnit, std::__1::allocator<AdblockPlus::DefaultTimer::TimerUnit> >::__push_back_slow_path<AdblockPlus::DefaultTimer::TimerUnit const&>(AdblockPlus::DefaultTimer::TimerUnit const&&&) vector:1575
    #4 0x10829e4bf in AdblockPlus::DefaultTimer::SetTimer(std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000l> > const&, std::__1::function<void ()> const&) vector:1596
    #5 0x1082beaff in AdblockPlus::JsEngine::ScheduleTimer(v8::Arguments const&) JsEngine.cpp:108
    #6 0x1082bd431 in (anonymous namespace)::SetTimeoutCallback(v8::Arguments const&) GlobalJsObject.cpp:40
    #7 0x1083b4cb5 in v8::internal::FunctionCallbackArguments::Call(v8::Handle<v8::Value> (*)(v8::Arguments const&)) arguments.cc:109
    #8 0x108406014 in v8::internal::MaybeObject* v8::internal::HandleApiCallHelper<false>(v8::internal::(anonymous namespace)::BuiltinArguments<(v8::internal::BuiltinExtraArguments)1>, v8::internal::Isolate*) builtins.cc:1272
    #9 0x108405b98 in v8::internal::Builtin_Impl_HandleApiCall(v8::internal::(anonymous namespace)::BuiltinArguments<(v8::internal::BuiltinExtraArguments)1>, v8::internal::Isolate*) builtins.cc:1289
    #10 0x1083f53eb in v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) builtins.cc:1288
    #11 0xf5ea27072cd  (<unknown module>)
    #12 0xf5ea2770daf  (<unknown module>)
    #13 0xf5ea2770c70  (<unknown module>)
    #14 0xf5ea27108f3  (<unknown module>)
    #15 0xf5ea2770855  (<unknown module>)
    #16 0xf5ea271b50f  (<unknown module>)
    #17 0xf5ea2770006  (<unknown module>)
    #18 0xf5ea276e618  (<unknown module>)
    #19 0xf5ea276e760  (<unknown module>)
    #20 0xf5ea272aee3  (<unknown module>)
    #21 0xf5ea2717e96  (<unknown module>)
    #22 0x108491881 in v8::internal::Invoke(bool, v8::internal::Handle<v8::internal::JSFunction>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*, bool*) execution.cc:119
    #23 0x108490d71 in v8::internal::Execution::Call(v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*, bool*, bool) execution.cc:182
    #24 0x10833dfc5 in v8::Script::Run() api.cc:2039
    #25 0x1082c0bfb in AdblockPlus::JsEngine::Evaluate(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) JsEngine.cpp:163
    #26 0x1082abec0 in AdblockPlus::FilterEngine::CreateAsync(std::__1::shared_ptr<AdblockPlus::JsEngine> const&, std::__1::function<void (std::__1::shared_ptr<AdblockPlus::FilterEngine> const&)> const&, AdblockPlus::FilterEngine::CreationParameters const&) FilterEngine.cpp:204
    #27 0x1082ac4a5 in AdblockPlus::FilterEngine::Create(std::__1::shared_ptr<AdblockPlus::JsEngine> const&, AdblockPlus::FilterEngine::CreationParameters const&) FilterEngine.cpp:212
    #28 0x108231831 in (anonymous namespace)::FilterEngineTestGeneric<LazyFileSystem, AdblockPlus::DefaultLogSystem>::SetUp() FilterEngine.cpp:58
    #29 0x108322861 in testing::Test* testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::TestFactoryBase, testing::Test*>(testing::internal::TestFactoryBase*, testing::Test* (testing::internal::TestFactoryBase::*)(), char const*) gtest.cc:2402

Thread T54 created by T0 here:
    #0 0x10a00fca6 in wrap_pthread_create (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x4cca6)
    #1 0x10829f1ff in std::__1::thread::thread<AdblockPlus::DefaultTimer::DefaultTimer()::$_0, void>(AdblockPlus::DefaultTimer::DefaultTimer()::$_0&&) thread:369
    #2 0x10829e108 in std::__1::thread::thread<AdblockPlus::DefaultTimer::DefaultTimer()::$_0, void>(AdblockPlus::DefaultTimer::DefaultTimer()::$_0&&) thread:365
    #3 0x10829df0f in AdblockPlus::DefaultTimer::DefaultTimer() DefaultTimer.cpp:25
    #4 0x10829e128 in AdblockPlus::DefaultTimer::DefaultTimer() DefaultTimer.cpp:24
    #5 0x1082be33e in AdblockPlus::CreateDefaultTimer() JsEngine.cpp:72
    #6 0x1081f4898 in CreateJsEngine(AdblockPlus::AppInfo const&) BaseJsTest.cpp:23
    #7 0x1081fe320 in BaseJsTest::SetUp() BaseJsTest.h:150
    #8 0x1082316f9 in (anonymous namespace)::FilterEngineTestGeneric<LazyFileSystem, AdblockPlus::DefaultLogSystem>::SetUp() FilterEngine.cpp:54
    #9 0x108322861 in testing::Test* testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::TestFactoryBase, testing::Test*>(testing::internal::TestFactoryBase*, testing::Test* (testing::internal::TestFactoryBase::*)(), char const*) gtest.cc:2402
    #10 0x108305d83 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) gtest.cc:2438
    #11 0x108305bab in testing::Test::Run() gtest.cc:2470
    #12 0x108306f90 in testing::TestInfo::Run() gtest.cc:2656
    #13 0x108308011 in testing::TestCase::Run() gtest.cc:2774
    #14 0x108313f61 in testing::internal::UnitTestImpl::RunAllTests() gtest.cc:4649
    #15 0x108322861 in testing::Test* testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::TestFactoryBase, testing::Test*>(testing::internal::TestFactoryBase*, testing::Test* (testing::internal::TestFactoryBase::*)(), char const*) gtest.cc:2402
    #16 0x108313943 in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) gtest.cc:2438
    #17 0x10831371b in testing::UnitTest::Run() gtest.cc:4257
    #18 0x108295510 in RUN_ALL_TESTS() gtest.h:2233
    #19 0x108295497 in main gtest_main.cc:37
    #20 0x7fffe2dc7234 in start (libdyld.dylib:x86_64+0x5234)

SUMMARY: AddressSanitizer: heap-use-after-free chrono:778 in std::__1::cv_status std::__1::condition_variable::wait_until<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > >(std::__1::unique_lock<std::__1::mutex>&, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)
Shadow bytes around the buggy address:
  0x1c0c000035a0: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
  0x1c0c000035b0: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
  0x1c0c000035c0: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
  0x1c0c000035d0: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
  0x1c0c000035e0: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
=>0x1c0c000035f0: fd fd fd fd fa fa fa fa[fd]fd fd fd fd fd fd fd
  0x1c0c00003600: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
  0x1c0c00003610: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
  0x1c0c00003620: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
  0x1c0c00003630: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
  0x1c0c00003640: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==41589==ABORTING

comment:14 Changed 9 months ago by hfiguiere

Crash filed as issue #5116.

comment:15 Changed 9 months ago by sergz

Additional info for my last comment.

Examples of stack traces when the app crashes:

>	tests.exe!v8::internal::Isolate::PerIsolateThreadData::Matches(v8::internal::Isolate * isolate, v8::internal::ThreadId thread_id) Line 428	C++
 	tests.exe!v8::internal::Isolate::ThreadDataTable::Lookup(v8::internal::Isolate * isolate, v8::internal::ThreadId thread_id) Line 1685	C++
 	tests.exe!v8::internal::Isolate::FindOrAllocatePerThreadDataForThisThread() Line 370	C++
 	tests.exe!v8::internal::StackGuard::FreeThreadResources() Line 540	C++
 	tests.exe!v8::internal::ThreadManager::FreeThreadResources() Line 380	C++
 	tests.exe!v8::Locker::~Locker() Line 111	C++
 	tests.exe!AdblockPlus::JsContext::~JsContext()	C++
 	tests.exe!`anonymous namespace'::StatThread::Run() Line 238	C++
 	tests.exe!AdblockPlus::Thread::CallRun(AdblockPlus::Thread * thread) Line 111	C++
 	kernel32.dll!@BaseThreadInitThunk@12()	Unknown
 	ntdll.dll!__RtlUserThreadStart()	Unknown
 	ntdll.dll!__RtlUserThreadStart@8()	Unknown
>	tests.exe!v8::internal::Isolate::PerIsolateThreadData::Matches(v8::internal::Isolate * isolate, v8::internal::ThreadId thread_id) Line 428	C++
 	tests.exe!v8::internal::Isolate::ThreadDataTable::Lookup(v8::internal::Isolate * isolate, v8::internal::ThreadId thread_id) Line 1685	C++
 	tests.exe!v8::internal::Isolate::FindOrAllocatePerThreadDataForThisThread() Line 370	C++
 	tests.exe!v8::internal::StackGuard::FreeThreadResources() Line 540	C++
 	tests.exe!v8::internal::ThreadManager::FreeThreadResources() Line 380	C++
 	tests.exe!v8::Locker::~Locker() Line 111	C++
 	tests.exe!AdblockPlus::JsContext::~JsContext()	C++
 	tests.exe!`anonymous namespace'::MoveThread::Run() Line 157	C++
 	tests.exe!AdblockPlus::Thread::CallRun(AdblockPlus::Thread * thread) Line 111	C++
 	kernel32.dll!@BaseThreadInitThunk@12()	Unknown
 	ntdll.dll!__RtlUserThreadStart()	Unknown
 	ntdll.dll!__RtlUserThreadStart@8()	Unknown

An example of stack trace of the main thread at this moment

>	tests.exe!_free_base(void * pBlock) Line 50	C
 	tests.exe!_free_dbg_nolock(void * pUserData, int nBlockUse) Line 1431	C++
 	tests.exe!_free_dbg(void * pUserData, int nBlockUse) Line 1265	C++
 	tests.exe!operator delete(void * pUserData) Line 54	C++
 	tests.exe!std::allocator<char>::deallocate(char * _Ptr, unsigned int __formal) Line 586	C++
 	tests.exe!std::_Wrap_alloc<std::allocator<char> >::deallocate(char * _Ptr, unsigned int _Count) Line 888	C++
 	tests.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy(bool _Built, unsigned int _Newsize) Line 2265	C++
 	tests.exe!std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> >() Line 965	C++
 	tests.exe!`eh vector destructor iterator'(void * ptr, unsigned int size, int count, void (void *) * pDtor)	C++
 	tests.exe!`dynamic atexit destructor for 'jsSources''()	C++
 	tests.exe!doexit(int code, int quick, int retcaller) Line 585	C
 	tests.exe!exit(int code) Line 395	C
 	tests.exe!__tmainCRTStartup() Line 247	C
 	tests.exe!mainCRTStartup() Line 164	C
 	kernel32.dll!@BaseThreadInitThunk@12()	Unknown
 	ntdll.dll!__RtlUserThreadStart()	Unknown
 	ntdll.dll!__RtlUserThreadStart@8()	Unknown

As it's visible it's at doexit, the object being destroyed is different, sometimes it's jsSources (as here), sometimes some test factories of gtest.

comment:16 Changed 8 months ago by sergz

  • Blocked By 5182 added

comment:17 Changed 7 months ago by sergz

  • Blocked By 5182 removed

comment:18 Changed 7 months ago by sergz

  • Blocking 3593 removed

comment:19 Changed 5 months ago by sergz

  • Blocked By 5179 added

Currently there are no race conditions in tests (except tests for default implementation of timer, #5455) because they are not using additional threads. The default implementation of timer allows to gracefully shut it down even if there are currently running tasks or tasks with a later firing time. The tasks don't keep permanently a strong reference to JsEngine.
However, the title of the issue is still relevant, it will be possible to achieve it after #5179.

Note: See TracTickets for help on using tickets.