nfs4: Fix rpc listener thread cancelation
recv on UDP sockets is not interrupted when the socket is closed. Additionaly, signals do not interrupt kernel threads, that is why new function interrupt_thread was implemented in order to cancel listener thread.
This commit is contained in:
parent
7fdee1565d
commit
e552920f09
@ -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);
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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<Thread> 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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user