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. This file is part of Sortix.
@ -41,6 +41,10 @@ public:
~PipeEndpoint(); ~PipeEndpoint();
bool Connect(PipeEndpoint* destination); bool Connect(PipeEndpoint* destination);
void Disconnect(); 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 read(ioctx_t* ctx, uint8_t* buf, size_t count);
ssize_t write(ioctx_t* ctx, const 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); 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); return Ref<StreamSocket>(NULL);
} }
client->outgoing.SetSIGPIPEDelivery(false);
server->outgoing.SetSIGPIPEDelivery(false);
client->is_connected = true; client->is_connected = true;
server->is_connected = true; server->is_connected = true;

View File

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