Cygwin: FIFO: fix clone
After copyto is called, make the new fhandler's pipe_name point to the new fhandler's pipe_name_buf, which is a *copy* of the old fhandler's pipe_name_buf. Previously, get_pipe_name would return the wrong result after a clone/dup, causing create_pipe_instance and open_pipe to fail. Also, stop the listen_client thread when cloning. Otherwise the thread can keep accepting connections that the cloned fhandler won't know about. Do this via a new method fhandler_fifo::stop_listen_client, extracted from fhandler_fifo::close.
This commit is contained in:
parent
c5bc7a8065
commit
7b28776d3f
|
@ -1280,6 +1280,7 @@ class fhandler_fifo: public fhandler_base
|
||||||
int disconnect_and_reconnect (int);
|
int disconnect_and_reconnect (int);
|
||||||
int add_client_handler ();
|
int add_client_handler ();
|
||||||
bool listen_client ();
|
bool listen_client ();
|
||||||
|
int stop_listen_client ();
|
||||||
public:
|
public:
|
||||||
fhandler_fifo ();
|
fhandler_fifo ();
|
||||||
bool hit_eof ();
|
bool hit_eof ();
|
||||||
|
@ -1326,7 +1327,12 @@ public:
|
||||||
{
|
{
|
||||||
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_fifo));
|
void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_fifo));
|
||||||
fhandler_fifo *fhf = new (ptr) fhandler_fifo (ptr);
|
fhandler_fifo *fhf = new (ptr) fhandler_fifo (ptr);
|
||||||
|
/* We don't want our client list to change any more. */
|
||||||
|
stop_listen_client ();
|
||||||
copyto (fhf);
|
copyto (fhf);
|
||||||
|
/* fhf->pipe_name_buf is a *copy* of this->pipe_name_buf, but
|
||||||
|
fhf->pipe_name.Buffer == this->pipe_name_buf. */
|
||||||
|
fhf->pipe_name.Buffer = fhf->pipe_name_buf;
|
||||||
for (int i = 0; i < nhandlers; i++)
|
for (int i = 0; i < nhandlers; i++)
|
||||||
fhf->fc_handler[i].fh = fc_handler[i].fh->clone ();
|
fhf->fc_handler[i].fh = fc_handler[i].fh->clone ();
|
||||||
return fhf;
|
return fhf;
|
||||||
|
|
|
@ -812,9 +812,9 @@ fifo_client_handler::close ()
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
fhandler_fifo::close ()
|
fhandler_fifo::stop_listen_client ()
|
||||||
{
|
{
|
||||||
int res = 0;
|
int ret = 0;
|
||||||
HANDLE evt = InterlockedExchangePointer (&lct_termination_evt, NULL);
|
HANDLE evt = InterlockedExchangePointer (&lct_termination_evt, NULL);
|
||||||
HANDLE thr = InterlockedExchangePointer (&listen_client_thr, NULL);
|
HANDLE thr = InterlockedExchangePointer (&listen_client_thr, NULL);
|
||||||
if (thr)
|
if (thr)
|
||||||
|
@ -825,19 +825,29 @@ fhandler_fifo::close ()
|
||||||
DWORD err;
|
DWORD err;
|
||||||
GetExitCodeThread (thr, &err);
|
GetExitCodeThread (thr, &err);
|
||||||
if (err)
|
if (err)
|
||||||
debug_printf ("listen_client_thread exited with code %d", err);
|
{
|
||||||
|
ret = -1;
|
||||||
|
debug_printf ("listen_client_thread exited with error, %E");
|
||||||
|
}
|
||||||
CloseHandle (thr);
|
CloseHandle (thr);
|
||||||
}
|
}
|
||||||
if (evt)
|
if (evt)
|
||||||
CloseHandle (evt);
|
CloseHandle (evt);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fhandler_fifo::close ()
|
||||||
|
{
|
||||||
|
int ret = stop_listen_client ();
|
||||||
if (read_ready)
|
if (read_ready)
|
||||||
CloseHandle (read_ready);
|
CloseHandle (read_ready);
|
||||||
if (write_ready)
|
if (write_ready)
|
||||||
CloseHandle (write_ready);
|
CloseHandle (write_ready);
|
||||||
for (int i = 0; i < nhandlers; i++)
|
for (int i = 0; i < nhandlers; i++)
|
||||||
if (fc_handler[i].close () < 0)
|
if (fc_handler[i].close () < 0)
|
||||||
res = -1;
|
ret = -1;
|
||||||
return fhandler_base::close () || res;
|
return fhandler_base::close () || ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
Loading…
Reference in New Issue