Fix filesystem sockets sending SIGPIPE on disconnect.

This commit is contained in:
Jonas 'Sortie' Termansen 2014-04-30 23:14:20 +02:00
parent 6774c79ba6
commit 0ebe5fc04d
3 changed files with 41 additions and 4 deletions

View File

@ -1,6 +1,6 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
This file is part of Sortix.
@ -41,6 +41,10 @@ public:
~PipeEndpoint();
bool Connect(PipeEndpoint* destination);
void Disconnect();
bool GetSIGPIPEDelivery();
bool SetSIGPIPEDelivery(bool deliver_sigpipe);
size_t Size();
bool Resize(size_t new_size);
ssize_t read(ioctx_t* ctx, uint8_t* buf, size_t count);
ssize_t write(ioctx_t* ctx, const uint8_t* buf, size_t count);
int poll(ioctx_t* ctx, PollNode* node);

View File

@ -418,6 +418,9 @@ Ref<StreamSocket> Manager::Accept(StreamSocket* socket, ioctx_t* ctx,
return Ref<StreamSocket>(NULL);
}
client->outgoing.SetSIGPIPEDelivery(false);
server->outgoing.SetSIGPIPEDelivery(false);
client->is_connected = true;
server->is_connected = true;

View File

@ -60,6 +60,8 @@ public:
void CloseReading();
void CloseWriting();
void PerhapsShutdown();
bool GetSIGPIPEDelivery();
void SetSIGPIPEDelivery(bool deliver_sigpipe);
ssize_t read(ioctx_t* ctx, uint8_t* buf, size_t count);
ssize_t write(ioctx_t* ctx, const uint8_t* buf, size_t count);
int read_poll(ioctx_t* ctx, PollNode* node);
@ -81,6 +83,7 @@ private:
size_t buffersize;
bool anyreading;
bool anywriting;
bool is_sigpipe_enabled;
};
@ -93,6 +96,7 @@ PipeChannel::PipeChannel(uint8_t* buffer, size_t buffersize)
this->buffersize = buffersize;
bufferoffset = bufferused = 0;
anyreading = anywriting = true;
is_sigpipe_enabled = true;
}
PipeChannel::~PipeChannel()
@ -170,9 +174,9 @@ ssize_t PipeChannel::write(ioctx_t* ctx, const uint8_t* buf, size_t count)
}
if ( !anyreading )
{
CurrentThread()->DeliverSignal(SIGPIPE);
errno = EPIPE;
return -1;
if ( is_sigpipe_enabled )
CurrentThread()->DeliverSignal(SIGPIPE);
return errno = EPIPE, -1;
}
if ( buffersize - bufferused < count ) { count = buffersize - bufferused; }
size_t writeoffset = (bufferoffset + bufferused) % buffersize;
@ -228,6 +232,18 @@ int PipeChannel::write_poll(ioctx_t* /*ctx*/, PollNode* node)
return errno = EAGAIN, -1;
}
bool PipeChannel::GetSIGPIPEDelivery()
{
ScopedLockSignal lock(&pipelock);
return is_sigpipe_enabled;
}
void PipeChannel::SetSIGPIPEDelivery(bool deliver_sigpipe)
{
ScopedLockSignal lock(&pipelock);
is_sigpipe_enabled = deliver_sigpipe;
}
PipeEndpoint::PipeEndpoint()
{
channel = NULL;
@ -286,6 +302,20 @@ int PipeEndpoint::poll(ioctx_t* ctx, PollNode* node)
: channel->write_poll(ctx, node);
}
bool PipeEndpoint::GetSIGPIPEDelivery()
{
return !reading ? channel->GetSIGPIPEDelivery() : false;
}
bool PipeEndpoint::SetSIGPIPEDelivery(bool deliver_sigpipe)
{
if ( !reading )
channel->SetSIGPIPEDelivery(deliver_sigpipe);
else if ( reading && deliver_sigpipe != false )
return errno = EINVAL, false;
return true;
}
class PipeNode : public AbstractInode
{
public: