From 92d7c1807e03d45d8e934459a7197f0b624a6d90 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Tue, 6 May 2014 19:12:44 +0200 Subject: [PATCH] Fix user-space filesystems not disconnecting properly. --- kernel/fs/user.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/kernel/fs/user.cpp b/kernel/fs/user.cpp index 31ef304b..e4cbffd2 100644 --- a/kernel/fs/user.cpp +++ b/kernel/fs/user.cpp @@ -134,7 +134,7 @@ class ChannelNode : public AbstractInode public: ChannelNode(); ChannelNode(Channel* channel); - ~ChannelNode(); + virtual ~ChannelNode(); void Construct(Channel* channel); virtual ssize_t read(ioctx_t* ctx, uint8_t* buf, size_t count); virtual ssize_t write(ioctx_t* ctx, const uint8_t* buf, size_t count); @@ -149,6 +149,7 @@ class Server : public Refcountable public: Server(); virtual ~Server(); + void Disconnect(); Channel* Connect(); Channel* Listen(); Ref BootstrapNode(ino_t ino, mode_t type); @@ -159,6 +160,7 @@ private: kthread_cond_t connecting_cond; kthread_cond_t connectable_cond; Channel* connecting; + bool disconnected; }; @@ -274,7 +276,7 @@ size_t ChannelDirection::Send(ioctx_t* ctx, const void* ptr, size_t least, size_ while ( true ) { if ( !still_reading ) - return errno = EPIPE, sofar; + return errno = ECONNRESET, sofar; if ( buffer_used < BUFFER_SIZE ) break; if ( least <= sofar ) @@ -316,7 +318,7 @@ size_t ChannelDirection::Recv(ioctx_t* ctx, void* ptr, size_t least, size_t max) if ( least <= sofar ) return sofar; if ( !still_writing ) - return errno = EPIPE, sofar; + return errno = ECONNRESET, sofar; if ( !kthread_cond_wait_signal(¬_empty, &transfer_lock) ) return errno = EINTR, sofar; } @@ -483,24 +485,34 @@ Server::Server() connecting_cond = KTHREAD_COND_INITIALIZER; connectable_cond = KTHREAD_COND_INITIALIZER; connecting = NULL; + disconnected = false; } Server::~Server() { } +void Server::Disconnect() +{ + ScopedLock lock(&connect_lock); + disconnected = true; + kthread_cond_signal(&connectable_cond); +} + Channel* Server::Connect() { Channel* channel = new Channel(); if ( !channel ) return NULL; ScopedLock lock(&connect_lock); - while ( connecting ) + while ( !disconnected && connecting ) if ( !kthread_cond_wait_signal(&connectable_cond, &connect_lock) ) { delete channel; return errno = EINTR, (Channel*) NULL; } + if ( disconnected ) + return delete channel, errno = ECONNREFUSED, (Channel*) NULL; connecting = channel; kthread_cond_signal(&connecting_cond); return channel; @@ -544,6 +556,7 @@ ServerNode::ServerNode(Ref server) ServerNode::~ServerNode() { + server->Disconnect(); } Ref ServerNode::open(ioctx_t* /*ctx*/, const char* filename, int flags,