What do I do When Dispose Method Fails? - c#

Well, here I am again with another frustrating question.
I need to end my main process and restart it, but I can't just end the application gracefully...
I am using a C# application in conjunction with proprietary (not to me) data capture hardware, so right there it's already complicated.
There is a scenario when my software is happily running, collecting its data as it should, when the hardware I'm interfacing with suddenly loses power and the connection to my application. My application eventually figures this out and I just need to dispose of my old connection, and make a new one to connect to my hardware again. Wrong...
Of course, the .Dispose() method on my object (the interface object with the hardware), that terminates the connection does nothing, and actually just locks in place forever when I try to run it. Apparently there is some kind of communication that never times out on the dispose method that requires the device to be connected when the disconnection happens. I didn't write the method, so I don't really know.
Finally, here's my question. The only way to get my application up and running again is to close it and reopen it. Of course, I can't actually close it nicely because I can't run the Dispose method. I am forced to end it's process via task-manager. Yes, the process, not just the application. If I just close it, the process will stay alive forever, I have no choice.
I need to find a way to automate this process assassination so my users can actually use it, but what can I do? I know process termination is taboo, but what options do I have?
I'd love to use Application.Restart(), but that doesn't work at all, my form doesn't even close, it just locks. Is there a way to axe the process just before telling itself to launch again? Maybe I can do this with a batch file or something? Application.Exit at least takes the form off the screen.
As of now, I'm killing it from Task Manager, or my users are killing it by popping the breaker on the PC. Considerably more harsh than anything software-wise.

Have you considered isolating the problematic component in another process? I know it sounds complicated, but if you create another "application" which solely exists as a conduit to your device, you can make your main application just start a new one of those if the old one becomes unresponsive. It can nuke the old one, start a new one, and be "clean" again.
It does mean all kinds of inter-process communication of course, but the general idea of isolating something flaky is often a useful one.

Assuming that it is Dispose() that is the problem and that there is a proper IDisposable pattern implementation where the finalizer calls Dispose() I think that a solution might be to call GC.SupressFinalize(objWithFailingDispose) to prevent Dispose from being called at all.
It is ugly, but I might work.

This question should probably be titled "What do I do when I'm dealing with a Dispose() method I can't change, and has been written without considering a very real and very troubling real-world scenario?" And my suggestion would be to write a better one!
The simplest approach would be to create a wrapper for the object that will be disposed, and then calling GC.SuppressFinalize(internalConnectionObject); if you've detected that the connection has dropped. That way, if it's not responsive, it won't get stuck, but if it's there, it will be disposed properly. Isolation is your friend when you have troublesome components.

Related

How to unload unsued COM objects/libraries after a complete restart?

Here is the thing. I'm connecting via COM to some devices at KNX/EIB. But sometimes - and I want to be ready for worst-case anyways - my application crashes leaving all objects and libraries exposed somewhere, somehow. I noticed when I restart the app I have trouble to get a connection again. I get an error for a connection procedure that is actually working well normally. Sometimes this connect procedure is working sometimes it is not, randomly. That is bad! After some time (several minutes) it seems to work again after a series of complete fails. But I think I see a pattern now. It doesn't work after a crash with no clean disconnect. My guess is there are objects that hold a connection to the device that us why I can't get a new connection. This is why I ask this question.
Question:
How do I unload those unused objects to kill undead connections?
How do I make Windows to check for unused libraries to be unloaded?
I just want to tell Windows, "I messed up badly and I need to continue my work. Please clean up my mess for me, so I can start fresh! Do I deserve a 2nd chance?"
Edit:
The scenario is the app has crashed and closed. I have no references to anything anymore. No finally clause or anything. The app can only be started again. What can I do to clean up the mess that has been made before, programmatically?
Edit 2:
Hans gave me the hint of killing the responsible server. So for now I solve that with calling taskkill on startup (at least as long I'm in dev). And it works!
C:\Windows\System32\taskkill.exe /F /IM Falcon.exe
This is the failure mode of an out-of-process COM server. If the client program crashes to the desktop without releasing the interface pointers then the server is completely unaware that the client isn't around anymore. And tends to get balky when you try to reconnect, many servers just permit one client.
By far the most common way that programmers induce this failure mode is by using a debugger. They'll click the Red Button or use the Stop Debugging command. Bam, no cleanup of course.
COM garbage-collects unused servers automatically. But that isn't particularly fast, takes an easy 10 minutes before it decides it needs to step in. And doesn't always work for every server, Office programs notoriously don't get cleaned-up for example.
Not much you can do about this when your app keels over in regular usage. Otherwise the kind of problem that killed middle-ware. Still, having such a mishap in a C# program is pretty unusual, the CLR releases interface pointers at program termination even when the app crashed with an exception. You'd have to have the very nasty kind of mishaps to bypass this, critical exceptions like ExecutionEngineException or the one this site is named after.
Don't focus too much on the Stop Debugging induced failures, it is normal and using Task Manager to kill the server is expected and required. Otherwise just be sure to get the nasty bugs out of your code and you won't have a problem. If you need more help then be sure to contact the owner of the server, be sure to have a small repro project available that demonstrates the issue.

Best way to make sure another process acquires a Mutex before moving on?

I'm not exactly sure the best way to go out about what I'm trying to do, so I thought I'd turn here for ideas.
I have N number of programs that all must communicate with one process, ProcA through a memory mapped file.
When I open any program in group N, it checks if ProcA has been opened, if not it launches it. Here is where the question of this comes in...
When ProcA is ready, I need to be able to communicate to the process that spawned it, that the mapped memory has been created and communication can begin.
I was thinking about using a Mutex to accomplish this. Have the spawning processing attempt to acquire and release a mutex in a loop, checking if it was the creator or not, until it gets a return that the mutex was created in other place. Even this though seems potentially problematic since as I said, N number of programs will be doing this at once and if multiple are spinning, acquiring and releasing like this, they'll see each other locking and think it's ProcA instead.
So, what's the best way for N number of processeses blocking until ProcA signals that it's open for business?
Thanks!
Edit
For further clarification, I've tried having the process that spawns ProcA create the memory map which ProcA can then take over. But I found I have the same problem, because the spawning process needs to know when to release the shared memory, if it does it before ProcA grabs it then the memory map is released.
Edit 2
I need to pass pointer data around between the two processes, thus memory mapped files are my only options, pipes, sockets, etc won't work for this.
I think what you should really look into IPC with WCF (it's an old article, but should give you the basics), this would be far better than your current approach and signalling each other with the Mutex.
But if you insist on using this approach, you can create a system wide (Global), or session wide (named) Mutex, and simply do WaitOne/ReleaseMutex. No need for looping, and you should try to stay away from this (looping) approach as you'll be unnecessarily wasting CPU cycles, but don't think there's much to it unless I'm missing something.

Destroying unmanaged objects in C#

I'm working on an application just now which uses a bunch of external DLLs to make a connection to a server somewhere. Oddly, the exposed methods for these DLLs allow a connection but NOT a disconnection or close. These libraries work fine unless you make a lot of subsequent calls to the server in one chunk, so what I decided to do was disconnect and reconnect after X amount of calls.
However, herein lies the issue. I cannot disconnect because no disconnect method is given. SO my question is, how can I totally kill this unmanaged object so I can recreate it again?
If you're using unmanaged resources in C# you should have your classes that use and interact with the unmanaged resources implementing IDisposable and creating and destroying them with using blocks.
If you can't disconnect, depending on exactly what you're interfacing sometimes setting the variable containing your unmanaged resource to null will clear some of it up. Really though, there's not a great deal you can do without proper disconnect/dispose methods.
You could manually close the underlying connection to the server. I cant help you any more with how to do that without knowing more about the service your consuming (HTTP TCP ect?). You could put a trace (like wireshark) up and see what's being transferred.
Bottom line though is their software is broken. Can you not contact the vendor?
The best solution I could find for this, was to run each call to the external DLL in it's own thread, which was eventually killed when the thread ended. This was the only resolution that worked, given I had no access to updated DLLs.

C# Do we need to close TCPClient by using TCPClient.Close if it is no more used?

I'm making a program which sends data to many TCP listeners. If one of the TCP Sending channel is no more used, do we need to close it using TCPClient.close. What happens if we leave it open?
Thanks!
I wouldn't use Close explicitly - I'd just dispose it via a using statement:
using (TcpClient client = ...)
{
// Use the client
}
What happens if we leave it open?
If neither side closes the connection, it'll be sitting there doing nothing, pointlessly.
If the other end closes the connection, I suspect you'll have a local connection in TIME_WAIT or something similar for a while; I don't know the exact details but it's not ideal.
The main point is that it may use up some system resources, and fundamentally it's not ideal. Is it going to cause your program to crash and your system to go crazy? Probably not - at least unless you're creating a huge number of these. It's still a good idea to dispose of anything with non-memory resources though.
If you leave it open, the GC (Garbage Collector) will in time dispose of your object.
With TCPClient, the finalizer (the code run when the GC cleans up your object) has a call to Dispose(), which in turn closes the connection and frees any OS resources used by it.
You don't know WHEN the GC does it's cleaning up, so this approach is undeterministic. This probably isn't a problem with one or two open connections, but you may starve the system of resources if you open a huge number of these.
A good practice would be to always dispose TCPClients when you're done with them, and this can easily be accomplished with the using block. (As shown in Jon Skeets answer...)

Is this a bad idea/practice what problems would I run into

I have a process that I need to make into a service. This process runs autonomously right now so there are no concerns with user interaction I just need to "turn" it into a service. I got to thinking about it and decided that I could just create a service that launched the process, this would give me the added benefit of having outside control of the process.. I could watch it for an unexpected exit and re-launch it.. I could also watch its memory usage and kill it if it gets out of hand. I dont think I have seen many other applications do this and I was thinking there must be a reason why so...
It's going to add complexity.
Instead of just having the process exist, you'll now need to make a second executable to "launch and monitor" this process. This adds overhead (the service and process both running), adds complexity, and makes life as a whole a bit more difficult.
That being said, if you've got a .NET Console application, turning it into a service is incredibly trivial. Your Main routine basically just gets moved into a method, and launched in a thread. Once you do that, the service application is effectively done - it's just configuring the service (which can be done in a designer) and overriding OnStart to spin up a thread and call your routine.
This is a good idea, but you've reinvented the wheel. What you're thinking of is essentially server monitoring. There are several high-quality open source implementations of what you want.
Pretty much anything that you can do this way you can do with less complexity by just putting the application logic in the service. Not to mention that you get Service Recovery for free by doing it in the service directly.

Categories

Resources