Open externl opened 1 month ago
It is not clear to me that this is a race condition issue. Doesn't Task
create a detached task that could run after main exits?
That was just a snippet of the test that was failing. It was not exiting main for a while after.
It's reproducible in just C++ .
#include <Ice/Ice.h>
int main(int argc, char *argv[])
{
int count = 0;
for (;;)
{
Ice::CommunicatorHolder ich(argc, argv);
auto communicator = ich.communicator();
std::thread t([communicator]
{
for (;;)
{
try {
communicator->stringToProxy("test:tcp -h 127.0.0.1 -p 10000");
} catch (Ice::CommunicatorDestroyedException &e) {
break;
}
} });
communicator->destroy();
t.join();
}
return 0;
}
❯ clang++ -std=c++17 test.cpp -lIce -I/Users/joe/Developer/zeroc-ice/ice/cpp/include -I/Users/joe/Developer/zeroc-ice/ice/cpp/include/generated -L/Users/joe/Developer/zeroc-ice/ice/cpp/lib -Wl,-rpath,/Users/joe/Developer/zeroc-ice/ice/cpp/lib -o test
❯ ./test
fish: Job 1, './test' terminated by signal SIGSEGV (Address boundary error)
After running this a bunch there seems to be a variety of failures you can get.
One issue is that endpoint factories set the instance member to nullptr during destroy, but access it without chekcing.
For example:
and:
A second issue is the endpoint factory manager clears the factories vector, while it is in use:
For example:
and:
We can fix this one by holding the mutex in destroy.
For "invalid endpoint" it is probably because, the factory was destroyed and removed, before it has a chance to parse the endpoint. We can fix ReferenceFactory to throw CommunicatorDestroyedException in this case.
I also got this crash with the same test:
* thread #2, stop reason = EXC_BAD_ACCESS (code=1, address=0x180)
* frame #0: 0x00000001023abb00 libIce.38a0.dylib`std::__1::shared_ptr<IceInternal::DefaultsAndOverrides>::get[abi:ue170006](this=0x0000000000000180) const at shared_ptr.h:871:16
frame #1: 0x000000010239bee0 libIce.38a0.dylib`std::__1::shared_ptr<IceInternal::DefaultsAndOverrides>::operator bool[abi:ue170006](this=0x0000000000000180) const at shared_ptr.h:903:16
frame #2: 0x000000010239be80 libIce.38a0.dylib`IceInternal::Instance::defaultsAndOverrides(this=0x0000000000000000) const at Instance.cpp:289:5
frame #3: 0x000000010259234c libIce.38a0.dylib`IceInternal::ProtocolInstance::defaultSourceAddress(this=0x0000600000b14518) const at ProtocolInstance.cpp:103:23
frame #4: 0x0000000102351264 libIce.38a0.dylib`IceInternal::IPEndpointI::initWithOptions(this=0x0000600001914018, args=size=0, oaEndpoint=false) at IPEndpointI.cpp:408:56
(lldb) frame select 3
frame #3: 0x00000001025922a8 libIce.38a0.dylib`IceInternal::ProtocolInstance::defaultSourceAddress(this=0x0000600001f80218) const at ProtocolInstance.cpp:103:23
100 const Address&
101 IceInternal::ProtocolInstance::defaultSourceAddress() const
102 {
-> 103 return _instance->defaultsAndOverrides()->defaultSourceAddress;
104 }
105
106 const EncodingVersion&
(lldb) print _instance
(const IceInternal::InstancePtr) nullptr {
__ptr_ = nullptr
While porting Swift to use async/await I got this crash
The code in question was running stringToProxy and destroy at the same time.