×

Discussion Board

Results 1 to 3 of 3
  1. #1
    Registered User
    Join Date
    Aug 2008
    Posts
    2

    CActive and Exit, zombie thread remains

    Hi!

    Strange situation. CActive object works ok, but after Exit() call i saw the thread is still running, like zombie process.

    I thinks problem in Active Object cancel implementation. Can you help, what's wrong there?

    My code:
    Code:
    #include <textresolver.h>
    #include <eikenv.h>
    #include "HttpRequest.h"
    
    CHttpRequest::CHttpRequest(): CActive(EPriorityStandard) {
    
    }
    
    CHttpRequest* CHttpRequest::NewLC() {
    	CHttpRequest* self = new (ELeave) CHttpRequest();
    	CleanupStack::PushL(self);
    	self->ConstructL();
    	return self;
    }
    
    CHttpRequest* CHttpRequest::NewL() {
    	CHttpRequest* self = CHttpRequest::NewLC();
    	CleanupStack::Pop(); // self;
    	return self;
    }
    
    void CHttpRequest::ConstructL() {
    	CActiveScheduler::Add(this); // Add to scheduler
    }
    
    
    CHttpRequest::~CHttpRequest() {	
    	Cancel();	
    }
    
    void CHttpRequest::DoCancel() {
    	Reset();
    }
    
    TInt CHttpRequest::RunError(TInt aError) {
    	CTextResolver *iTextResolver = CTextResolver::NewLC();
    	_LIT(KHeaderText, "ERROR");
    	TPtrC title(KHeaderText);
    	CEikonEnv::Static()->InfoWinL(title, iTextResolver->ResolveErrorString(aError));	
    	delete iTextResolver;
    	
    	Reset();
    	return aError;
    }
    
    void CHttpRequest::Reset() {
    
    	switch ( iState ) {
    		case EReceive:
    		case ESend:
    			iSocket.CancelAll();
    			iSocket.Close();
    			
    		case EConnecting:
    			iResolver.Cancel();
    			iResolver.Close();			
    			
    		case EResolving:
    			iConn.Close();
    			
    		case EInitConnection:			
    			iSockServ.Close();
    			
    		case EIdle:
    			break;
    	}
    	iState = EIdle;
    }
    
    
    
    void CHttpRequest::makeRequest(CBufBase *anBuffer, CHttpRequestObserver *anObserver) {
    	iState = EInitConnection;
    	iOutBuffer = anBuffer;
    	iObserver = anObserver;
    	
    	iSockServ.Connect();
    	SetActive();
    }
    
    void CHttpRequest::InitConnection() {
    	iState = EResolving;
    	
    	aPrefs.SetDialogPreference(ECommDbDialogPrefPrompt);
    	aPrefs.SetDirection(ECommDbConnectionDirectionOutgoing);
    	
    	iConn.Open(iSockServ);
    	iConn.Start(aPrefs, iStatus);	
    	SetActive();
    }
    
    void CHttpRequest::ResolveHost() {
    	iState = EConnecting;
    
    	_LIT(KHostName, "host.com");
    	iResolver.Open(iSockServ, KAfInet, KProtocolInetTcp, iConn);
    	iResolver.GetByName(KHostName, tName, iStatus);
    	SetActive();
    }
    
    void CHttpRequest::Connect() {
    	iState = ESend;
    	iAddr = tName().iAddr;
    	iAddr.SetPort(80);
    	
    	iSocket.Open(iSockServ, KAfInet, KSockStream, KProtocolInetTcp, iConn);
    	iSocket.Connect(iAddr, iStatus);
    	SetActive();
    }
    
    void CHttpRequest::Send() {
    	iState = EReceive;
    	iSocket.Write(_L8("GET / HTTP/1.0\r\nHost: host.com\r\n\r\n"), iStatus);
    	SetActive();	
    }
    
    void CHttpRequest::Receive(TBool bContinue) {
    	iState = EReceive;
    	iOutBuffer->InsertL(iOutBuffer->Size(), iNetBuffer);
    	iNetBuffer.Zero();
    	if ( bContinue ) {		
    		iSocket.RecvOneOrMore(iNetBuffer, 0, iStatus, iDummy);		
    		SetActive();
    	}
    }
    
    void CHttpRequest::RunL() {
    	if ( iStatus.Int() == KErrNone || iStatus.Int() == KErrEof ) {
    		switch ( iState ) {
    			case EInitConnection:
    				InitConnection();
    				iObserver->ToState(EInitConnection);
    				break;
    				
    			case EResolving: 
    				ResolveHost();
    				iObserver->ToState(EResolving);
    				break;
    				
    			case EConnecting: 
    				Connect();
    				iObserver->ToState(EConnecting);
    				break;
    				
    			case ESend:
    				Send();
    				iObserver->ToState(ESend);
    				break;
    				
    			case EReceive:
    				switch ( iStatus.Int() ) {
    					case KErrNone:
    						Receive(ETrue);
    						iObserver->ToState(EReceive);			
    						break;
    						
    					case KErrEof:
    						Receive(EFalse);
    						iObserver->Fetched(); // successfully
    						Reset();
    						break;				
    				}
    				break;
    		}		
    	} else {
    		iObserver->Canceled();
    		Reset();
    		User::LeaveIfError(iStatus.Int());
    	}
    }
    CActive instance creation:
    Code:
    void CMyAppUi::ConstructL() {
    	// Initialise app UI with standard value.
    	BaseConstructL(CAknAppUi::EAknEnableSkin); 	
    	
    	iBuf = CBufFlat::NewL(256); // buffer for CHttpRequest
    	req = CHttpRequest::NewL(); // 
    	
    	iAppView = CMyAppView::NewL(ClientRect()); // Create view object
    	AddToStackL(iAppView);
    }
    Destructor:
    Code:
    CMyAppUi::~CMyAppUi() {
    	if (iAppView) {
    		RemoveFromStack(iAppView);
    		delete iAppView;
    	}
    	delete iBuf;
    	delete req;	
    }
    Invoke:
    Code:
    void CMyAppUi::HandleCommandL(TInt aCommand) {
    ...
    		case EAbout:
    			req->makeRequest(iBuf, this);
    			break;
    ...
    }

  2. #2
    Nokia Developer Moderator
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    28,688

    Re: CActive and Exit, zombie thread remains

    Check the value of your state variable, and if Reset goes to the branch you expect. Although the usual approach is Cancel-ing things in DoCancel, but Close-ing them after the Cancel returns in the destructor, your Reset method should be fine too.
    Where do you see your thread as alive, and how long? Does EikStart::RunApplication return?

  3. #3
    Registered User
    Join Date
    Aug 2008
    Posts
    2

    Re: CActive and Exit, zombie thread remains

    Quote Originally Posted by wizard_hu_ View Post
    Check the value of your state variable, and if Reset goes to the branch you expect. Although the usual approach is Cancel-ing things in DoCancel, but Close-ing them after the Cancel returns in the destructor, your Reset method should be fine too.
    Reset calls immediatly after fetching URL, with iState = 5 (EReceive), so code correctly closes all instances of iSocket, iResolver, iConn and iSockServ and sets iState = 0 (EIdle).


    Quote Originally Posted by wizard_hu_ View Post
    Where do you see your thread as alive, and how long? Does EikStart::RunApplication return?
    I'm using On-Device debug (because emulator is too slow for debugging).
    If i run debug session without running CActive, application shutdown correctly and EikStart::RunApplication is returns. But if during session i try to fetch url, by running CActive, after Exit() call, App TRK show's me "Welcome to TRK.. " but EikStart::RunApplication is not returns. On debug tab i see my process which has one active thread running.

    I wait some time (by drinking one cup of tea) but thread still running. Sad.

Similar Threads

  1. Replies: 3
    Last Post: 2008-06-03, 12:22
  2. RSocket in emulator...
    By FireStoke in forum Symbian Networking & Messaging (Closed)
    Replies: 24
    Last Post: 2005-11-11, 11:15

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×