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:
Pawel Dziepak 2012-05-30 22:09:31 +02:00
parent 7fdee1565d
commit e552920f09
5 changed files with 37 additions and 2 deletions

View File

@ -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);

View File

@ -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()
{

View File

@ -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();

View File

@ -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;

View File

@ -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)
{