Error
Executing the below in Visual Studio triggers "Debug Error! abort() has been called":
if(m_handle==INVALID_HANDLE_VALUE) return(false); // no return here, therefore m_handle is valid (?)
if(!m_connected){ // some bool indicating a connection doesn't already exist
if(ConnectNamedPipe(m_handle,NULL)==0){ // --- Abort() message triggered here ----
// ...
}
}
Context
The above code is part of a connectClient()
method of a PipeFunctor
class that overloads the function call operator ()
; and within that overloaded function is a call to connectClient()
:
void PipeFunctor::operator()() {
connectClient(); // PipeFunctor::connectClient() called here
// ...
}
The connectClient()
method is indirectly called via the functor passed to thread, i.e.:
PipeFunctor pipeF();
// ...
std::thread (std::ref(pipeF));
Hypothesis
When connectClient()
is directly called (as shown below), the same offending ConnectNamedPipe()
statement executes without a Debug abort() error:
PipeFunctor pipeF();
// ...
pipeF.connectClient();
This leads me to believe that it is the thread execution statement, std::thread (std::ref(pipeF));
, that causes the issue downstream.
1. Is there a way I can begin a new thread by passing it a functor object that contains, and subsequently calls, the ConnectNamedPipe()
function, without producing this debug abort() error?
2. What's the best way to resolve this issue?
All suggestions appreciated.
Thanks!
Additional Info:
The m_handle
variable is (seemingly successfully) created from within the connectClient()
(as shown below) method prior to the offending function ConnectNamedPipe()
being called:
if(!pipename || *pipename==0) return(false); // no return here. pipeName is a correctly initialized LPTSTR variable
m_handle = CreateNamedPipe(pipename,PIPE_ACCESS_DUPLEX,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,256*1024,256*1024,5000,NULL);
if(m_handle==INVALID_HANDLE_VALUE){ // produces if(false)
wprintf(L"Creating pipe '%s' failed\n",pipename);
return(false);
}
PipeFunctor pipeF();
is a function declaration (a function named pipeF
taking no arguments and returning a PipeFunctor
). It is not a variable declaration, like you probably intended. PipeFunctor pipeF;
is a variable declaration, as is PipeFunctor pipeF{};
.
In any case, when using std::thread
, you are passing it a reference to pipeF
. My guess is that pipeF
is going out of scope and being destroyed before the thread has a chance to call its operator()
. If a std::thread
callback throws an uncaught exception (such as by accessing data members of an invalid PipeFunctor
object), std::terminate()
gets called, which in turn calls std::abort()
by default.