Repository navigation
exit race between main and worker threads #25007
Description
Activity
- addedconfirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.processIssues and PRs related to the process subsystem.Issues and PRs related to the process subsystem.lib / srcIssues and PRs involving general changes in the lib/ or src/ directories.Issues and PRs involving general changes in the lib/ or src/ directories.workerIssues and PRs related to the worker_threads module and Worker API.Issues and PRs related to the worker_threads module and Worker API.
on Dec 13, 2018 /cc @nodejs/workers @nodejs/process
on a side note: why would worker module be loaded even in the absence of
--experimental-workerflag? I believe the answer is that all the internal modules are loaded at bootstrap, irrespective of their requirement at runtime.Can we change that? At least in this case, it will save a lot of resources (thread, memory) for use cases that do not require worker?
@bengl was looking at this earlier but I don't know if he has anything to add (and if he did, he'd probably put it in the other issue). Pinging him here anyway just in case...
why would worker module be loaded even in the absence of
--experimental-workerflag?As far as I can tell, it’s only the native binding that’s loaded unconditionally (to figure out whether we’re in a worker or not during bootstrap).
I believe the answer is that all the internal modules are loaded at bootstrap, irrespective of their requirement at runtime.
That’s not the case;
test/parallel/test-bootstrap-modules.jstests this.At least in this case, it will save a lot of resources (thread, memory) for use cases that do not require worker?
The memory overhead is probably not huge, and just loading the worker module does not spawn any threads on its own.
$ gdb ./node_g (gdb) b pthread_create Breakpoint 1 at 0xd2fe40 (gdb) r Starting program: ./node_g [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib64/libthread_db.so.1". Breakpoint 1, 0x0000000000d2fe40 in pthread_create@plt () Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.el7.x86_64 libgcc-4.8.5-28.el7.x86_64 libstdc++-4.8.5-28.el7.x86_64 (gdb) bt #0 0x0000000000d2fe40 in pthread_create@plt () #1 0x0000000000fd8acf in uv_thread_create (tid=0x3396790, entry=0xe9be78 <node::WorkerThreadsTaskRunner::DelayedTaskScheduler::Start()::{lambda(void*)#1}::_FUN(void*)>, arg=0x3395f60) at ../deps/uv/src/unix/thread.c:213 #2 0x0000000000e9bf1a in node::WorkerThreadsTaskRunner::DelayedTaskScheduler::Start ( this=0x3395f60) at ../src/node_platform.cc:63 #3 0x0000000000e998e8 in node::WorkerThreadsTaskRunner::WorkerThreadsTaskRunner ( this=0x3395bf0, thread_pool_size=4) at ../src/node_platform.cc:178 #4 0x0000000000ea795f in __gnu_cxx::new_allocator<node::WorkerThreadsTaskRunner>::construct<node::WorkerThreadsTaskRunner<int&> > (this=0x7fffffffdcfd, __p=0x3395bf0) at /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/ext/new_allocator.h:120 #5 0x0000000000ea68c4 in std::allocator_traits<std::allocator<node::WorkerThreadsTaskRunner> >::_S_construct<node::WorkerThreadsTaskRunner<int&> >(std::allocator<node::WorkerThreadsTaskRunner>&, std::allocator_traits<std::allocator<node::WorkerThreadsTaskRunner> >::__construct_helper*, (node::WorkerThreadsTaskRunner<int&>&&)...) (__a=..., __p=0x3395bf0) at /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/alloc_traits.h:253 #6 0x0000000000ea54d5 in std::allocator_traits<std::allocator<node::WorkerThreadsTaskRunner> >::construct<node::WorkerThreadsTaskRunner<int&> >(std::allocator<node::WorkerThreadsTaskRunner>&, node::WorkerThreadsTaskRunner<int&>*, (node::WorkerThreadsTaskRunner<int&>&&)...) (__a=..., __p=0x3395bf0) at /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/alloc_traits.h:399 #7 0x0000000000ea37aa in std::__shared_ptr<node::WorkerThreadsTaskRunner, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<node::WorkerThreadsTaskRunner>, int&> ( this=0x7fffffffde30, __tag=..., __a=...) at /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/shared_ptr_base.h:1124 #8 0x0000000000ea1692 in std::shared_ptr<node::WorkerThreadsTaskRunner>::shared_ptr<std::alloca---Type <return> to continue, or q <return> to quit--- tor<node::WorkerThreadsTaskRunner>, int&> (this=0x7fffffffde30, __tag=..., __a=...) at /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/shared_ptr.h:316 #9 0x0000000000e9fe4e in std::allocate_shared<node::WorkerThreadsTaskRunner, std::allocator<node::WorkerThreadsTaskRunner>, int&> (__a=...) at /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/shared_ptr.h:588 #10 0x0000000000e9e7fb in std::make_shared<node::WorkerThreadsTaskRunner, int&> () at /opt/rh/devtoolset-3/root/usr/include/c++/4.9.2/bits/shared_ptr.h:604 #11 0x0000000000e9a18f in node::NodePlatform::NodePlatform (this=0x3395b00, thread_pool_size=4, tracing_controller=0x3395920) at ../src/node_platform.cc:293 #12 0x0000000000dbbdcc in Initialize (this=0x3359680 <node::v8_platform>, thread_pool_size=4) at ../src/node.cc:239 #13 0x0000000000dc26d4 in node::InitializeV8Platform (thread_pool_size=4) at ../src/node.cc:1893 #14 0x0000000000dc2cd7 in node::Start (argc=1, argv=0x338b4d0) at ../src/node.cc:2122 #15 0x0000000001e13199 in main (argc=1, argv=0x7fffffffe048) at ../src/node_main.cc:126 (gdb)
@addaleax - this is what I see, am I missing something?
ok, apologies; those are normal worker threads created every time at the bootup. I got confused with
worker_thread's thread; my bad.@gireeshpunathil Okay, that clears it up :)
I think
worker_thread’s threads are affected as well, though…- removedworkerIssues and PRs related to the worker_threads module and Worker API.Issues and PRs related to the worker_threads module and Worker API.
on Dec 13, 2018 ok, I edited the description to remove worker module from the limelight. I was misguided by the word
workerin the WorkerThreadsTaskRunner - that led to writing this test too.So just to clarify (for myself and others): now this test case only solves the purpose to easily recreate / pronounce the issue through many worker threads, but workers are not real culprits.
As far as I can tell, it’s only the native binding that’s loaded unconditionally (to figure out whether we’re in a worker or not during bootstrap).
I believe that should be unnecessary - opened #25017
Part of debugging #24921 I happened to run the entire CI with underscored exit replacing normal exit in
Environment::Exit. The only test that fails inpseudo-tty/test-set-raw-mode-reset-process-exit. I am not advocating in favor of_exitas the favored fix, just stating it here.58 remaining items
- added a commit that references this issue
on Feb 8, 2019 - added a commit that references this issue
on Feb 8, 2019 - added a commit that references this issue
on Feb 13, 2019 - added 2 commits that reference this issue
on Mar 27, 2019 - added a commit that references this issue
on Apr 17, 2019 - added 2 commits that reference this issue
on Apr 28, 2019 - added 2 commits that reference this issue
on May 10, 2019 - added 2 commits that reference this issue
on May 16, 2019
worker, process, srcSample test case to reproduce the issue:
The flakiness of the test is largely influenced by the thread scheduling order / number of CPUs / load on the system.
First reported in AIX and Linux through
sequential/test-cli-syntax.js. The more you run, the more variety of scenarios you get: SIGSEGV, SIGABRT, SIGILL... depends on at what point the main and the worker threads are.The root cause is that there is no specified order / identified ownership of C++ global objects that being destructed between threads.
Refs: #24403