diff --git a/headers/os/drivers/KernelExport.h b/headers/os/drivers/KernelExport.h index 3e2e5848dd..14c707dc66 100644 --- a/headers/os/drivers/KernelExport.h +++ b/headers/os/drivers/KernelExport.h @@ -138,6 +138,7 @@ extern bool cancel_timer(timer *t); /* kernel threads */ extern thread_id spawn_kernel_thread(thread_func function, const char *name, int32 priority, void *arg); +extern status_t interrupt_thread(thread_id id); /* signal functions */ extern int send_signal_etc(pid_t thread, uint signal, uint32 flags); diff --git a/src/add-ons/kernel/file_systems/nfs4/Connection.cpp b/src/add-ons/kernel/file_systems/nfs4/Connection.cpp index 094dfe6da3..c1b7e89f75 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Connection.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Connection.cpp @@ -55,7 +55,8 @@ Connection::Connection(const sockaddr_in& addr, Transport proto, bool markers) Connection::~Connection() { - kclosesocket(fSock); + if (fSock != -1) + kclosesocket(fSock); mutex_destroy(&fSockLock); } @@ -184,6 +185,9 @@ Connection::_ReceivePacket(void** pbuffer, uint32* psize) result = errno; free(buffer); return result; + } else if (size == 0) { + free(buffer); + return ECONNABORTED; } *pbuffer = buffer; @@ -257,6 +261,15 @@ Connection::Reconnect() } +void +Connection::Disconnect() +{ + int sock = fSock; + fSock = -1; + kclosesocket(sock); +} + + status_t Connection::Init() { diff --git a/src/add-ons/kernel/file_systems/nfs4/Connection.h b/src/add-ons/kernel/file_systems/nfs4/Connection.h index 6ac07d318a..11029c3230 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Connection.h +++ b/src/add-ons/kernel/file_systems/nfs4/Connection.h @@ -39,6 +39,7 @@ public: inline status_t Receive(void** buffer, uint32* size); status_t Reconnect(); + void Disconnect(); static status_t Init(); static status_t CleanUp(); diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp index f5fa966d54..280be81a68 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp @@ -86,6 +86,8 @@ Server::Server(Connection* conn, ServerAddress* addr) Server::~Server() { fThreadCancel = true; + fConnection->Disconnect(); + interrupt_thread(fThread); delete fConnection; @@ -157,9 +159,12 @@ status_t Server::Repair() { fThreadCancel = true; + interrupt_thread(fThread); + status_t result = fConnection->Reconnect(); if (result != B_OK) return result; + wait_for_thread(fThread, &result); return _StartListening(); } @@ -197,7 +202,8 @@ Server::_Listener() if (req != NULL) { *req->fReply = reply; req->fEvent.NotifyAll(); - } + } else + delete reply; } return B_OK; diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index 6c95268c44..022b8a1173 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -3007,6 +3007,20 @@ kill_thread(thread_id id) } +status_t +interrupt_thread(thread_id id) +{ + Thread* thread = Thread::GetAndLock(id); + if (thread == NULL) + return B_BAD_THREAD_ID; + BReference threadReference(thread, true); + ThreadLocker threadLocker(thread, true); + + InterruptsSpinLocker schedulerLocker(gSchedulerLock); + return thread_interrupt(thread, false); +} + + status_t send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize) {