Thread Priority and Delayed Cancellation

This document describes problems caused due to delayed cancellation of threads.

The basic problem is when Thread A has previously requested a Notification of some status change and now requests that the Notification be cancelled.

Thread A starts Thread B to talk to the Server. Thread B sends the cancellation request to the Server and sends a completion message back to Thread A to say that the cancel request has been sent to the Server.

In the past Thread B would not have returned until the Server cancellation had completed. But with SMP the cancellation request may be placed on a second CPU and delayed for various reasons, while Threads A and B continue. It is possible for a Notification event to occur at this point and a panic will occur when the Notification arrives without a process to handle it.

The single core device had fewer problems with thread priority issues like delayed cancellation, because the Server ran with higher priority and completed the cancellation before returning control to Thread B. On a multiple core system, different threads run in parallel and this may lead to errors.

You should be aware that deadlocks or panics can be caused due to delayed cancellation of threads and write your code to avoid it.

Example

One possible solution is to send the cancel completion message from the RunL() function call of the server.

Figure 1. Error in cancellation sequence

Client code

// [...]
//Whilst running
  iNotifier.RequestNotification(iStatus);
// [...]
//Some part of the client is now waiting for 
  notifications on iStatus


// [...] at some point during exit
  iNotifier.CancelNotification();
  iNotifier.Close();  
// Notifier session can be taken down now.

Server code

void CCommsdatNotifierSessionHandler::RegisterNotifyL(
	const RMessage2& aMessage)
    {
…
    iMessage = aMessage;
…
        iProperty.Subscribe(iStatus);
        SetActive();
 void CCommsdatNotifierSessionHandler::CancelNotify(
		const RMessage2& aMessage)
    {
    iProperty.Cancel();
    …
    aMessage.Complete(KErrCancel);
    }

void CCommsdatNotifierSessionHandler::RunL()
    {
…
    iMessage.Complete(…);
…
    }

Solution for server code

void CCommsdatNotifierSessionHandler::RegisterNotifyL(
	const RMessage2& aMessage)
    {
…
    iMessage = aMessage;
…
        iProperty.Subscribe(iStatus);
        SetActive();
 Void CCommsdatNotifierSessionHandler::CancelNotify(const RMessage2 &aMessage)
{
iProperty.Cancel();
...
iCancelMessage = aMessage;
}

Void CCOmmsdatNotifierSessionHandler::RunL()
{
...

iMessage.Complete(...);
iCancelMessage.Complete(KErrNone);

...
}
Related concepts
SMP Developer Tips