Fix pipe destruction race condition.

This commit is contained in:
Jonas 'Sortie' Termansen 2015-10-09 01:40:55 +02:00
parent 12b5044bc7
commit 2727d9fb50
1 changed files with 13 additions and 10 deletions

View File

@ -59,7 +59,6 @@ public:
~PipeChannel(); ~PipeChannel();
void CloseReading(); void CloseReading();
void CloseWriting(); void CloseWriting();
void PerhapsShutdown();
bool GetSIGPIPEDelivery(); bool GetSIGPIPEDelivery();
void SetSIGPIPEDelivery(bool deliver_sigpipe); void SetSIGPIPEDelivery(bool deliver_sigpipe);
size_t ReadSize(); size_t ReadSize();
@ -90,6 +89,7 @@ private:
size_t pretended_read_buffer_size; size_t pretended_read_buffer_size;
size_t pledged_read; size_t pledged_read;
size_t pledged_write; size_t pledged_write;
unsigned long closers;
bool anyreading; bool anyreading;
bool anywriting; bool anywriting;
bool is_sigpipe_enabled; bool is_sigpipe_enabled;
@ -110,6 +110,7 @@ PipeChannel::PipeChannel(uint8_t* buffer, size_t buffersize)
receiver_system_tid = 0; receiver_system_tid = 0;
pledged_read = 0; pledged_read = 0;
pledged_write = 0; pledged_write = 0;
closers = 0;
} }
PipeChannel::~PipeChannel() PipeChannel::~PipeChannel()
@ -119,26 +120,27 @@ PipeChannel::~PipeChannel()
void PipeChannel::CloseReading() void PipeChannel::CloseReading()
{ {
kthread_mutex_lock(&pipelock);
anyreading = false; anyreading = false;
kthread_cond_broadcast(&writecond); kthread_cond_broadcast(&writecond);
PerhapsShutdown(); read_poll_channel.Signal(ReadPollEventStatus());
write_poll_channel.Signal(WritePollEventStatus());
kthread_mutex_unlock(&pipelock);
unsigned long count = InterlockedIncrement(&closers).n;
if ( count == 2 )
delete this;
} }
void PipeChannel::CloseWriting() void PipeChannel::CloseWriting()
{ {
kthread_mutex_lock(&pipelock);
anywriting = false; anywriting = false;
kthread_cond_broadcast(&readcond); kthread_cond_broadcast(&readcond);
PerhapsShutdown();
}
void PipeChannel::PerhapsShutdown()
{
kthread_mutex_lock(&pipelock);
read_poll_channel.Signal(ReadPollEventStatus()); read_poll_channel.Signal(ReadPollEventStatus());
write_poll_channel.Signal(WritePollEventStatus()); write_poll_channel.Signal(WritePollEventStatus());
bool deleteme = !anyreading & !anywriting;
kthread_mutex_unlock(&pipelock); kthread_mutex_unlock(&pipelock);
if ( deleteme ) unsigned long count = InterlockedIncrement(&closers).n;
if ( count == 2 )
delete this; delete this;
} }
@ -404,6 +406,7 @@ void PipeEndpoint::Disconnect()
channel->CloseReading(); channel->CloseReading();
else else
channel->CloseWriting(); channel->CloseWriting();
channel = NULL;
reading = false; reading = false;
} }