This project is read-only.

"The connection is already being dialed." error. (YES I am disposing!!)

Oct 8, 2010 at 4:21 AM
Edited Oct 8, 2010 at 4:22 AM

I'm trying to use DotRas to dial a 3G connection via USB modem. Normally it works fine, however sometimes (for no apparent reason) I get the error "the modem is busy" both in DotRas and also the modem's native app.

In the native app, I click "redial" a few times and it eventually works again, however with DotRas the only result I ever get after the "modem is busy" error is "This connection is already being dialed."

I've used the VS debugger to check that there are no active connections immediately after the error, so there is nothing to hang up. The dialer IsBusy status is false. I "reset" the dialer (dispose, then re-init the credentials options etc) after every dial attempt, the dispose code being:

this.dialer.Dispose();

Is this the right way to do it? What am I missing here?

As soon as I restart the program, I am given the "modem is busy" error again, allowing me to attempt redialing.

Edit: I am using SDK v1.2, on Visual Studio 2005 on Windows XP.

Oct 8, 2010 at 4:58 AM

I've seen many problems with these kind of devices over the past few years, most of which were hardware or driver related problems. That or Windows not recognizing what's going on and losing track of the device status.

The error you'd normally see if you weren't disposing of the component would be "This connection is already being dialed." if you were dialing asynchronously. However since you are disposing the component, I can only imagine the problem could have something to do with the modem being busy and Windows doesn't know what to do with it so the connection gets stuck in a strange state. The IsBusy property on the dialer only reflects the state of that instance of the RasDialer component, it does not know what Windows is doing since it could be dialing the connection as well. Based on what you're telling me, the native app is probably communicating directly with the device rather than routing through RAS in Windows.

A couple questions...

  1. Are you dialing the connection synchronously or asynchronously (the Dial or DialAsync method respectively)? If you're dialing asynchronously, you might want to see if the modem gives you the same results while dialing synchronously.
  2. Have you tried dialing the connection through Windows? DotRas is merely a wrapper for the Windows RAS API, which theoretically you should see the same results in Windows assuming you're not stopping debugging right after you initiate dialing (even I do that occasionally). Internally the dispose method makes sure the component releases any active connection attempt in progress before the component is released.

We can start here and see where the conversation leads us. Hopefully we can identify where the problem is, but I'm relatively certain it isn't with the RasDialer component or how you're using it.

- Jeff

Oct 8, 2010 at 5:15 AM
Edited Oct 8, 2010 at 5:15 AM

Hi Jeff,

Thanks for the speedy response. I tried your suggestions with very interesting results...

1) I was dialing asynchronously. If I change it to dial synchronously, I get a different error message ("The connection was interrupted.") but after retrying a few times, it works!!

2) Yes I have tried that (when dialing asynchronously), when my app is stuck on "This connection is already being dialed" then Windows shows the same error when trying to dial. HOWEVER, as soon as I close my app, I can dial the connection through Windows with no problems!!

I think the DotRas library is hanging onto something when dialing asynchronously that it shouldn't be.

 

Oct 8, 2010 at 6:21 AM
Edited Oct 8, 2010 at 6:23 AM

So you're still seeing an error even when dialing synchronously? Also, what's the error code you're seeing on the exception while dialing synchronously?

When the component dials synchronously the connection attempt is completely handled within the Windows RAS API, which it sounds like your device is still having problems even when the RasDialer component is removed from the connection attempt. All it would do in that scenario is initiate the dialing attempt, and Windows takes over from there. The only things the RasDialer component hangs on to for asynchronous calls is the callback that was passed to the API and the handle returned from the call for cancelling the connection attempt.

Also, how were you checking whether there were any active connections in the IDE? I'm assuming you were calling RasConnection.GetActiveConnections(). If you were, the connection wouldn't be in the collection unless the connection attempt had completed successfully. If it's still connecting, the connection doesn't show up which is a limitation of the RasEnumConnections API: http://msdn.microsoft.com/en-us/library/aa377284(VS.85).aspx

We'll have to continue this tomorrow, it's getting late here and I have to get to bed. Talk to you later!

Edit: If you can get the stack trace when the exception was thrown, that could be helpful as well.

Oct 8, 2010 at 6:43 AM

Hi Jeff,

The error encountered with dialing synchronously is error code 668. Note that since the redial error is intermittent, I'm reproducing it by attempting to dial with the modem not plugged in. This generates the same symptoms "modem busy" symptoms with the modem's native app. As soon as I plug the modem in, the synchronous method works but the async method doesn't.

So the sync method is a perfectly fine solution for me at the moment; it throws an exception when it should but recovers gracefully.

Wrt checking active connections, yes I was issuing an immediate GetActiveConnections() call.

I'm sorry I can't help you with a stack trace, it's getting a bit late here too and I already cleaned out all of my async code :(

Oct 8, 2010 at 2:29 PM
Edited Oct 8, 2010 at 7:24 PM

This sounds vaguely familiar to http://dotras.codeplex.com/Thread/View.aspx?ThreadId=50436. You might want to read through that thread, Keith has been a long time user of the product and has seen some issues with USB devices. I don't think you're having the same problems he is, however the information may be useful to you.

I think I have an idea what may be causing the problem, though I'm not certain. Going to copy this to a work item to start tracking resolution.

Oct 8, 2010 at 2:29 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Oct 11, 2010 at 4:32 AM

Not sure if you're tracking the work item or this discussion, but check the work item for the proposed fix attached to it. See the comments on the work item for more information.

Oct 23, 2010 at 4:10 PM
Edited Oct 23, 2010 at 4:24 PM

Hello Jeff:

I am using the most current code 67737 in my application, which supposedly fixes the above issue. I am still experiencing a problem with exactly the same symptoms as above. It was possible to replicate the issue on ANY test machine I tried. All you need to do it to put the machine with active PPTP connection into sleep, then wake it up. After that, it is not possible to restore the connection until the application is restarted.

1) Upon waking from sleep/hibernation, Disconnected handler is called by RasConnectionWatcher

2) At this stage I attempt to reconnect _asynchronously_, only to get the following error:

OpenPort, status: ok

OpenPort, status: The modem (or other connecting device) is already in use or is not configured properly.

DialCompleted: DotRas.RasDialException: The modem (or other connecting device) is already in use or is not configured properly.

The first two lines are output from StateChanged callback of RasDialer, the last line is from DialCompleted callback.

 

3) After the above error, I keep trying to reconnect using DialAsync, with each subsequent attempt failing with the following error:

DotRas.RasException: This connection is already being dialed.   at DotRas.Internal.ThrowHelper.ThrowRasException(Int32 errorCode)   at DotRas.Internal.RasHelper.Dial(String phoneBookPath, RASDIALPARAMS parameters, RASDIALEXTENSIONS extensions, RasDialFunc2 callback, RASEAPF eapOptions)   at DotRas.RasDialer.InternalDial(Boolean asynchronous)   at DotRas.RasDialer.DialAsync()   at ...

 

At this stage, if I check for active connections using "DotRas.RasConnection.GetActiveConnectionByName", my connection is not there. If I look in Control Panel -> Network Connections, I see the connection as Disconnected.

I have tried many approaches. I tried calling Dispose method of RasDialer in DialCompleted callback when there is a failure. I tried calling Dispose on the old RasDialer object and creating a new RasDialer object for each connection retry. Nothing helps, unless I close the application and start it again. 

Any ideas?

 

P.S.: I tried connecting synchronously, just to see whether the problem is related to connection method, but received exactly the same messages. After sleep, PPTP connection breaks. If I attempt to reconnect using synchronous Dial, I first get the error:

DotRas.RasDialException: The modem (or other connecting device) is already in use or is not configured properly.

And on subsequent attempts get the error:

DotRas.RasException: This connection is already being dialed.

So, this does not appear to be related to synchronous or asynchronous connection method.

Oct 23, 2010 at 5:01 PM

Well, there is no patch checked in that fixes the above issue. I'm assuming you were referring to check-in ID 67729, that check-in resolved an issue with the project hiding the actual error rather than showing the underlying problem. So the connection has already connected when you put the machine into sleep mode? I'll see if I can replicate the problem over here, but we may have a problem since the machine I connect to is the same machine I'd be putting to sleep (I test using virtual machines).

Oct 24, 2010 at 3:41 PM
Edited Oct 25, 2010 at 5:49 AM

Hello Jeff:

Yes, when I put my system into sleep, it already has a live PPTP connection, which was established using DotRas. It does not matter whether synchronously or asynchronously. Yes, I did refer to fix 67729, since it was made in response to another person reporting a very similar issue (probably the same issue).

I have replicated the bug on 1 real system  (Windows 7), and 2 virtual systems (using VMWare- XP Pro and Vista). To replicate:

 

1) Establish connection to VPN server using PPTP (I don't know- maybe any other connection type will work)

2) Register callback with RasConnectionWatcher to report when connection breaks

3) Put the system to sleep

4) Wake the system up (doesn't matter how long it was in sleep mode- 1 second should be sufficient)

5) You will receive callback from RasConnectionWatcher - at this point the connection is shown as "Disconnected" in Network Connections

6) IMMEDIATELY Attempt to reconnect using Dial or DialAsynch. In 95% cases you will receive an error:

DotRas.RasDialException: The modem (or other connecting device) is already in use or is not configured properly.

In other 5% of cases, or when you put a Sleep or MessageBox before reconnecting (i.e. don't reconnect immediately), it will work. If you do not get the error, put to sleep, wake up again.

7) Assuming you got the error in 6), try to reconnect again. From now on you'll always receive the following error:

DotRas.RasException: This connection is already being dialed.

At this stage it does not matter whether I call "DialAsyncCancel" or "Dispose" after each attempt, or whether I create a new RasDialer object- I will always get the above error.

The important point, which demonstrates that this is not the problem of Microsoft rasdial- is that the issue is gone as soon as I restart the C# application.

Which leads me to conclude that DotRas is not releasing something it should release after the first failed attempt. I can only guess what- you should have a much better understanding of the code.

 

Thanks for your help and thanks for the otherwise great library.

 

Michael

Oct 24, 2010 at 5:00 PM

Well, you've given me a much better bug report - though it's going to take me some time to get it diagnosed. I just formatted my machine (kept getting BSODs from it). I still have to reinstall everything, just finished getting the operating system back on it a few minutes ago.

Oct 25, 2010 at 3:00 PM

Hi Jeff:

Any news? If you wish, I can provide you with PPTP server details to ease your testing :)

Please let me know.

Regards,

Michael

 

Oct 25, 2010 at 3:19 PM

Hi Jeff:

Please let me know how to contact you by the e-mail of messaging, so that I can give you parameters of PPTP account you can use for testing.

I have set up an account at "vpn.hidemyass.com" which is valid until December 27.

Cheers,

Michael

Oct 25, 2010 at 6:11 PM

Jeff, I have made a sample project that makes it very easy to replicate the error. It has all the information pre-entered. Simply compile and run. Please check your e-mail- I have sent it as an attachment. Please confirm when the bug is replicated.

Cheers,

Michael

Oct 25, 2010 at 10:04 PM
Edited Oct 25, 2010 at 10:21 PM

Ok, so here's what I've found...

From what I can tell this looks like a state manager consistency problem with RAS. Now before you say I'm simply trying to pass the blame to Microsoft, read what I have to say first. Also, this is not intended to blame anyone, this is merely one of those nuances we find as we work with the RAS API. Most of these situations have been identified earlier, and documented within the help documentation.

From your sleep mode scenario, you're creating a race condition between the network interface initialization and the VPN connection by trying to redial it so quickly after the machine has been brought back out of sleep. You can tell this by the error "The modem (or other connecting device) is already in use or is not configured properly." It's not that the device is already in use, the network interface just hasn't finished reinitializing yet. Before that error is reported by the DialCompleted event, the connection has already been checked whether it's active and disconnected if it was active (not only connected, even if it was still being dialed). This is normally what keeps the connection from going into an inconsistent state. However, in this situation the connection is not being reported as active, and forcably calling HangUp on a connection that received this error returns a "The connection was terminated." 668 error, indicating it cannot be released. Both the DialAsyncCancel and Dispose methods on RasDialer calls HangUp internally after determining whether it's an active connection. Since Windows doesn't report the connection as being active, it isn't disconnected. Also even if you force Windows to try and disconnect it, it won't do it (this returns the 668 error code). This is why you couldn't get it to fix itself earlier by calling DialAsyncCancel or Dispose methods on RasDialer.

By increasing the amount of time delayed when Windows reports the connection has been disconnected, and when you start to redial the connection fixed the problem every time. I'm not talking about increasing it to 4 or 5 seconds, I increased it to 60 seconds to ensure the network interfaces had plenty of time to reinitialize before attempting to dial the connection again. The reason behind the app being restarted may simply be Windows recognizing the connection state is broken, and when it fixes itself; however I cannot say that with absolute certainty because I'm not on the Windows core team. Currently there is only one object shared between asynchronous calls, and that's the address to the callback method which is used for connection state updates by RasDialer. I tried passing a new instance of the callback to the API, but it did not do anything to fix the situation. You mentioned earlier that both synchronous and asynchronous calls had the same result, on a synchronous call nothing is shared. A new instance of the struct is created and passed entirely on its own to the RasDial API. This further leads me to believe it's a state consistency problem. This same scenario can always be replicated by dialing a connection asynchronously, putting a breakpoint inside of the StateChanged event handler, and then pressing stop on your IDE while debugging. Your next attempt at dialing the connection synchronously or asynchronously will cause an exception with "This connection is already being dialed." as the message. However, in this scenario you'll need to reboot your machine to fix the problem. Under most conditions, I keep the state manager from going into an inconsistent state by aborting a connection in progress if the component is disposed. However, this scenario is out of my control for keeping the state manager consistent.

Also, just a helpful hint based on what I saw in your sample you sent me... if you set the SynchronizingObject property on the RasDialer and RasConnectionWatcher components you won't have to do the thread synchronization yourself. All of the multi-threaded components included in the project have this property exposed to ease development.

Hope all this helped,

- Jeff

Edit: I wanted to add, while I was testing on my wifi card I could see the connection being redialed before the network card reconnected to my network. Also wanted to clarify some of my points.

Oct 26, 2010 at 3:14 PM

Hello Jeff:

I noticed that you don't need to delay 60 seconds before reconnecting after sleep. For example, if I put a MessageBox right before the connect- then the application reconnects just fine, even if I keep the MessageBox open for even a couple of seconds. Try modifying the sample code, adding MessageBox line:

 

   private void buttonConnect_Click(object sender, EventArgs e)      

 {

            MessageBox.Show("!");

 

Put the system to sleep, wake it up and IMMEDIATELY close the MessageBox. It will connect just fine, no matted how quickly you close the MessageBox.

 

What part of RAS is being released by Windows when application exits? There MUST be a way of doing that without closing the application. Is there a DLL to unload, resources to free, etc? This is a very serious bug that renders DotRas virtually useless for situations when connection needs to be kept at all times.

Right now there is no mechanism of doing this gracefully and ensuring this works every time. I believe this should be a priority item before 1.2 becomes a Release version...

Cheers,

Michael

Oct 26, 2010 at 3:20 PM

Hi ...

I was following this thread carefully to see what will be the solution to the raised problem. I'm doing an application that must keep the connection all the time and reconnect when the system wake up ...

Michael, you found a partial solution, now, Did you try to send automatically the clic or < ENTER > to the messagebos just when it appear? Maybe ... that can hack (eventually) and get the desire result.

Oct 26, 2010 at 3:45 PM

Hi Jonatan:

Thanks for the tip. I just tried that. Now before I open the MessageBox, I also set a timer for 1 (ONE!) millisecond. When timer fires, I send the Esc key to the MessageBox:

SendKeys.SendWait("{ESC}"); 

The connection reconnects perfectly every time, even though I only wait for 1 millisecond before closing the MessageBox! There goes Jeff's argument about having to wait 60 seconds for the network interface to initialize!

Work for me to keep the connection alive at the moment. It is a HORRIBLE, HORRIBLE HACK, though. Why should displaying a MessageBox affect operation of Ras dialer?

Cheers,

Michael

Oct 26, 2010 at 3:56 PM

Exactly ... that's the way using ... sendkey function.

Yes, you're right is awful hack ... but that work perfectly for the moment.

One question: what function were you using or in what way were you setting your system to wait ... for example 10 seconds? I mean, without using messagebox ...

Exists many ways to do it: I just want to check if trying different ways without using the meessagebox hacking works.

I think SLEEP(x) function will not work ... maybe just setting a timer, or a loop ... will work ... will be good idea to try ...

Cheers,

johnatan

Oct 26, 2010 at 8:22 PM

Hi Michael,

I was making some test, just for curiosity as this time, as you mentioned the tip worked like a charm except that is an horrible hack. So I was wondering if using messagebox function everything work fine maybe making a simple call to peekmessage of windows APUI works too, instead of using MessageBox (if this works too the Jeff will get more ideas on how to fix the bug).

{
   internal class NativeMethods
   {
       [StructLayout(LayoutKind.Sequential)]
       public struct Message
       {
           public IntPtr hWnd;
           public IntPtr msg;
           public IntPtr wParam;
           public IntPtr lParam;
           public uint time;
           public System.Drawing.Point p;
       }
       [System.Security.SuppressUnmanagedCodeSecurity]
       [DllImport("User32.dll", CharSet=CharSet.Auto)] //import the User32.dll to get the PeekMessage method
        public static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags);
   }

private bool AppStillIdle
{
   get
   {
       NativeMethods.Message msg;
       return !NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
   }
}

while(AppStillIdle)  && (time_is_less_than_?_milliseconds)
   { 
       DoEvents(); //maybe this call ins't necessary. The idea is to avoid the use of Sleep or in the previous case the messagebox and timer hack.
   }

You can try to check if that work, the trick here is the call to PeekMessage.

Cheers,

Johnatan.

Oct 26, 2010 at 10:26 PM
Edited Oct 27, 2010 at 2:59 PM
TheBishop wrote:

What part of RAS is being released by Windows when application exits? There MUST be a way of doing that without closing the application. Is there a DLL to unload, resources to free, etc? This is a very serious bug that renders DotRas virtually useless for situations when connection needs to be kept at all times.

That's the problem, I don't know. The most I can do is ask a question on the Microsoft social community and hope someone answers. However, most of my questions out there regarding the internals of RAS have gone unanswered thus far so I'm not going to hold my breath. Perhaps managing the loading and unloading of Rasapi32.dll will fix the issue. I only load a couple assemblies from RAS for p/invoke calls. Though if the app that uses DotRas also happens to be using the assembly for something else, the other app is going to have problems with their own p/invoke calls.

There is nothing at all shared between synchronous calls, you can look at the code and see that for yourself. The only thing that is shared between asynchronous calls is the callback which points to the private method in the component to handle notifications from RAS. Those notifications then bubble up through the StateChanged event. Even if the shared callback is a problem, that wouldn't affect a synchronous call having the same issue since it isn't passed to it.

I still have other bugs I'm trying to take care of before the 1.2 RC2 release, and I have no intention of just ignoring this. If I can fix it, I will.

Edit: I manually tried to unload the Rasapi32.dll last night as I mentioned above without success. Perhaps the problem isn't with RasDialer, but with the RasConnectionWatcher and how it's being interacted with by the applications.

Oct 28, 2010 at 6:02 AM

Well, 5 hours spent today on this and I think I have to give it up for the night. I'm starting to go crosseyed looking at the code, and it's getting late.

From what I saw, my use of the ThreadPool.RegisterWaitForSingleObject method within RasConnectionWatcher may be part of the problem and the reason why showing a MessageBox or using a break point fixes the issue. The only similiarity I can see between those is the message pump is allowed to continue processing.  I haven't done a lot of research on it yet, just preliminary investigation as to what could be causing the issue. I tried managing the thread for the disconnect notice manually, but didn't see any change. I do feel fairly confident (around 75-80%) that the problem is within the RasConnectionWatcher class and not with the RasDialer class.

I also tested disabling the NIC after I connected to the VPN, and didn't see any problems with it. So, this could be a problem specific with the machine coming out of sleep. Has anyone tested this with hibernation?

- Jeff

Oct 29, 2010 at 5:02 AM

Well, I found the issue and it was exactly where I thought it was. Need to do some redesign on the class, but it was with the RegisterWaitForSingleObject causing the problem. There were two threads coming in simultaneously, a BandwidthRemoved notification and the Disconnected event you were consuming. With both of them coming in, it looks like there was a blocking issue somewhere down the line. Removing the lock on the callback didn't take care of the issue, and even if it had I wouldn't have been able to use it. If two notifications came in simultaneously while the connections were being processed that could have lead to a problem while comparing the states. With that said, I might have to pull out the state checking stuff from the class so I don't have to lock it while processing, not exactly sure yet. I'll find out more as I work on the component and test this scenario.

- Jeff

Oct 29, 2010 at 5:42 PM

Hello Jeff:

Thanks for all the hard work you are putting into this. I'm very impressed by the level of support you are providing for a free product.

I hope you'll be able to find some sort of quick-fix soon, as I am about to resort to ugly hacks, like putting all DotRas code into a separate executable and killing that executable to free the deadlock.

I already tried putting DotRas code into a separate AppDomain and unloading that domain after each unsuccessful connection  attempt, but that didn't work for some reason. Maybe because I have a reference to DotRas in my project (although DotRas is only used in the other AppDomain).

Thanks again,

Michael

 

Oct 29, 2010 at 6:25 PM

I wouldn't start thanking me yet, it was so late last night that I forgot how I fixed it and I can't get it to work again. At least I know what's doing it, just gotta figure out what I did to fix it... again.

Oct 29, 2010 at 11:07 PM

hi jeff,

sorry i haven't been able to help you with the debugging, it's been too crazy over here to revert the codebase back to the async version to get the report you were after.

as michael said, thanks for putting so much support behind your product, your efforts are greatly appreciated!

jonathan

Nov 1, 2010 at 8:48 PM

Hi Jeff:

Any luck with the fix? Have you felt an inspiration that enabled you re recall the fix that you made? :)

Cheers,

Michael

Nov 1, 2010 at 10:06 PM

Ok, so after a LOT of work on this thing today I made some excellent progress and came up with a proposed fix. Check the associated work item to download the proposed patch, and let me know what happens... http://dotras.codeplex.com/workitem/12104

My original idea with the RasConnectionWatcher was wrong (as much as I hate to admit it). I couldn't get any consistency with the component even after spending about 20 hours working on it over the weekend along with this afternoon. So I went with another approach that perhaps the connection was being left open even though it was technically being disconnected. Once dialed using the test app Michael sent me, I would reconnect but the initial dial attempt would send a 633 error indicating the modem was not configured properly. At this point, the connection would be put into the open state, but when the RasDialer checked whether the connection was active before terminating it, RAS would not indicate it was active. Perhaps because it was not far enough along in the connection process to be considered active since it failed when opening the port. The biggest issue is if the connection was disconnected in this state it would throw a 668 error indicating the connection was already terminated. So I basically just hide the 668 error from being thrown if a connection is already disconnected and HangUp is called.

I have tested the fix all the way down to 1 ms on the redial timer, so we should be good to go.

Nov 2, 2010 at 2:44 PM

Wow, thanks, Jeff! The fixed version is working PERFECTLY! After wakeup, it fails ONCE while the device is still not re-initialized, then succeeds on the next try! This is great!

This should also fix similar problems reported to us by other users. It should basically solve all problems of similar nature when Ras Dialer fails in one of the first connection steps.

Thanks for all your help. DotRas is truly a great library!

Michael

Nov 2, 2010 at 3:04 PM

Good to hear, I'll get the changes checked in and close the work item. It'll be included with the 1.2 RC2 release for additional testing. I've also added a couple unit tests around HangUp to ensure I don't change the method to throw the 668 exception in the future.

Nov 10, 2010 at 12:27 AM

The fix worked for me too. I trust that Jeff's patch is probably more robust than mine. I'll roll with his.

On another note: The DotRAS code base is very clean. It was a pleasure to work with.

Nov 10, 2010 at 1:22 AM

Glad to hear it worked! I've tentatively scheduled the RC2 release for the 15th of this month, but it depends on another work item I have in progress that's almost done.

You can thank StyleCop for the cleanliness! :)