Canceling of RConnection::Start
Dear Nokians,
please help me with the following problem...
When initializing a socket connection, I construct:
- RSocketServ,
- RConnection,
- RHostResolver,
- RSocket
in this order. All operations that can be done in asynchronous way, well, are.
One of those operations is RConnection::Start(TConnPref& aPref, TRequestStatus& aStatus).
First of all: is there any way how to change [I]the default timeout[/I] on this operation? When the current level of mobile signal is bad (but not completely zero), this operation may linger for half eternity before giving up and returning an error. OK, it is not really "half eternity", but at least 30, and sometimes over 60 seconds. I would like to limit it to, say, 10 seconds, since it rarely succeeds after that time.
Second, [I]how to cancel the operation[/I]? When I wrap the RConnection into a CActive subclass, and then try to invoke Cancel() on that object when RConnection::Start is active, the whole thread freezes even if the DoCancel() method is empty.
Re: Canceling of RConnection::Start
Uh, it seems that this guy had a similar problem ... in 2006! He was using the synchronous version of Start(), but the nonresponsive behavior on device seems to be fairly similar.
[url]http://www.developer.nokia.com/Community/Discussion/showthread.php?83845-RConnection-Start-never-retrun[/url]
Re: Canceling of RConnection::Start
[QUOTE=MKechlibar;901631]
Second, [I]how to cancel the operation[/I]? When I wrap the RConnection into a CActive subclass, and then try to invoke Cancel() on that object when RConnection::Start is active, the whole thread freezes even if the DoCancel() method is empty.[/QUOTE]
Do you wish to cancel the ongoing HTTP transaction or what?
Re: Canceling of RConnection::Start
[QUOTE=vineet.jain;901647]Do you wish to cancel the ongoing HTTP transaction or what?[/QUOTE]
No.
This happens way before any network protocol operations like HTTP request/response. I thought it was obvious. RConnection does not have anything in common with specific protocols like HTTP. It represents a network device in the OS.
In detail. If I want to set up a socket connection (for any purpose), I go like this:
1. At first, I connect to RSocketServ.
2. Then, I try to Open() and Start() the RConnection for the particular Access Point.
3. Then, after the Open() and Start() of the RConnection succeeds, I run RHostResolver to find the address of the host.
4. Then, I Open() and Connect() the RSocket to the remote host.
5. And only then I perform some specific network operations. Your HTTP would happen here, in step 5. But in case of the problem with RConnection, the sequence does not proceed here; it ends (aborts) already in step 2, and it ends in a mess.
This is the sequence recommended by Nokia API Documentation, and it works acceptably for me, with the exception of the situation when I try to connect over GPRS and the signal is really bad (but nonzero). In such case, the operation RConnection::Start(), which is invoked in step 2, will block the thread, and, [U]if done in an Active Object, it can't be canceled in any way while pending - the corresponding CancelStart() function just does not exist[/U] in the RConnection public API.
Note that this problem does not happen in the emulator, only on real devices.
I wonder how could one work around this problem. I recently tried invoking RConnection::Close() instead of the missing CancelStart(), and the situation got better, but not perfect.
Re: Canceling of RConnection::Start
Starting again from scratch may behave better, so after RConnection::Close you may try if issuing RSocketServ::Close improves stability, or anything.
Re: Canceling of RConnection::Start
[QUOTE=wizard_hu_;901651]Starting again from scratch may behave better, so after RConnection::Close you may try if issuing RSocketServ::Close improves stability, or anything.[/QUOTE]
Yeah, it does, [I]provided[/I] that you can actually close the connection, which is not taken for granted.
For example / zum Beispiel / például / například:
Implementation like this:
[CODE]class CPrepare_AO : public CActive
{
public:
IMPORT_C CPrepare_AO();
IMPORT_C void StartConnection(RConnection& aConnection, TCommDbConnPref& aPref);
virtual void RunL();
virtual void DoCancel();
};
EXPORT_C CPrepare_AO::CPrepare_AO() : CActive(EPriorityStandard) { CActiveScheduler::Add(this); }
EXPORT_C void CPrepare_AO::StartConnection(RConnection& aConnection, TCommDbConnPref& aPref)
{
aConnection.Start(aPref, iStatus);
SetActive();
}
void CPrepare_AO::RunL()
{
// Some code for success, irrelevant here.
}
void CPrepare_AO::DoCancel()
{
// Do nothing!! There is no specific code for canceling the connection
}
[/CODE]
has the following sweet property: [B]if[/B] your attempt to Start() does not succeed fast (and it does not, if you attempt to connect over GPRS on a bad signal), then simply invoking Cancel() on the above mentioned active object [B]hangs[/B] the entire thread, even though DoCancel() implementation is empty.
It seems that RConnection gone wrong is a very dangerous object to touch.
Re: Canceling of RConnection::Start
Ok, by saying RConnection::Start is active, i thought you meant a request is underway & you want to cancel that.
Re: Canceling of RConnection::Start
There is no such thing as do-nothing in DoCancel. Put the Close there in this case, that should stop the operation (though it may also bring down your code with a panic, I tried this kind of code, but have not tested it extensively).
Remember what is inside CActive::Cancel, it is more-or-less[CODE]void CActive::Cancel()
{
if(IsActive())
{
DoCancel();
User::WaitForRequest(iStatus);
}
}[/CODE]perhaps with some extra stuff, but the important part is the WaitForRequest: something has to be done in order to have the request completed early, otherwise it will wait for the 'original' completion.
Re: Canceling of RConnection::Start
[QUOTE=wizard_hu_;901658]There is no such thing as do-nothing in DoCancel. Put the Close there in this case.
Remember what is inside CActive::Cancel, it is more-or-less[CODE]void CActive::Cancel()
{
if(IsActive())
{
DoCancel();
User::WaitForRequest(iStatus);
}
}[/CODE]perhaps with some extra stuff, but the important part is the WaitForRequest: something has to be done in order to have the request completed early, otherwise it will wait for the 'original' completion.[/QUOTE]
Good to know. Didn't know that before. This, on the other hand, indicates that the omission of a Cancel operation for RConnection::Start() from the RConnection API is quite a serious design error.
I made an experiment, which looks a bit different, but, in the end, probably results in the same behavior.
(from the outside of the CPrepare_AO object...)
[CODE]
if (iPrepare_AO->IsActive())
{
iConnection.Close();
iPrepare_AO->Cancel();
}[/CODE]
So far, it seems to behave better than before.