We have a large e-business application server that is out of our control, we can not modify it in any way shape or form. The company behind this application server will also not modify it to our customers requirements. This is due to the fact that they see us as a competitor and they do not wish the customer to use our application as a front end to their application.
Our desktop application uses web services to communicate with this application server and each login from the desktop occupies a user slot on the server. The application server offers no functionality that enables us to figure out if a user slot is taken or not. The best solution would be for us to develop an application that sits in the middle of the application server and our desktop client, this application would manage the allocation and deallocation of user slots and the problem is solved. This solution has be declined as the customer does not want to install our application on the e-business application server as that would void the user support of said e-business server, the alternative would be an extra server but that is something they don't want to deal with.
Which leaves us with the solution that our desktop application has write access to a shared folder. Each desktop application has a UID and we use that UID together with the user slot id and create a file UID.UserSlotId.locked. This would mean that each time a connection is made the desktop application would need to check this shared location and make sure they are not about to use a UserSlotId that is taken.
Now I now that the locked file is a terrible solution but the customer has requested this and no matter how much we inform them that this will never be a water tight solution they still want to go ahead. They are under the assumption that a 98% solution is a good solution. So what can the StackOverflow community offer in the way of advice with dealing with such a file locking system?
Open the lock file in Write mode and keep it open while the application uses a slot.
private static void TakeFistUnusedLock(FileStream[] currentLock)
{
for (int i = 1; i < 5; i++)
{
try
{
var fs = File.OpenWrite(Path.Combine(Path.GetTempPath(), "DbLock", i.ToString() + ".lock"));
currentLock[i - 1] = fs;
Console.WriteLine("Got lock " + i);
break;
}
catch (Exception) { }
}
}
I tested like this
FileStream[] currentLock = new FileStream[5];
var path = Path.Combine(Path.GetTempPath(), "DbLock");
DirectoryInfo di = new DirectoryInfo(path);
di.Create();
TakeFistUnusedLock(currentLock);
TakeFistUnusedLock(currentLock);
TakeFistUnusedLock(currentLock);
currentLock[1].Dispose(); // release lock 2
TakeFistUnusedLock(currentLock);
output was
Got lock 1
A first chance exception of type 'System.IO.IOException' occurred in mscorlib.dll
Got lock 2
A first chance exception of type 'System.IO.IOException' occurred in mscorlib.dll
A first chance exception of type 'System.IO.IOException' occurred in mscorlib.dll
Got lock 3
A first chance exception of type 'System.IO.IOException' occurred in mscorlib.dll
Got lock 2
Instead of keeping the currentLock array you only store one lock per application. You need to store the opened FileStream to make sure the file stays open in write mode. To release the lock you dispose the stored FileStream, then the write lock on the file is released.
This method ensures that the locks are released even if your application crashes.
Related
Our application is using CefSharp version 73.1.130. The issue only occurs on a small number of internal workstations within our organization. Worth noting, we are also seeing the same error with CefSharp version 92. Another strange thing is that it the issue is consistent, but only when the web apps are launched through certain navigations. Other navigations work consistently for these users.
We use RegisterJsObject to register a javascript object with browser. If I understand correctly, asynchronous binding is preferred moving forward.
The issue presents as strange/unexpected behavior in the hosted web application due to failure to retrieve context from the host WinForms application. The behavior would suggest a failure to register/bind the js object with the RegisterJsObject method. However, that method is not throwing an exception.
Enabled Cef logging showed the following error:
ERROR:JavascriptRootObjectWrapper.cpp(34)] IBrowserProcess is null, unable to bind object
After looking into the code, it appears the location that the value pointed to by "IBrowserProcess" is set is in WcfEnabledSubProcess::OnBrowserCreated (https://github.com/cefsharp/CefSharp/blob/cefsharp/73/CefSharp.BrowserSubprocess.Core/WcfEnabledSubProcess.cpp). I was able to build CefSharp and add additional logging to that method.
On my workstation (I'm not affected by the issue), I get through OnBrowserCreated with no exceptions. However, on my coworkers workstation I see the following line is failing:
...
channelFactory->Open();
auto browserProcess = channelFactory->CreateChannel();
auto clientChannel = ((IClientChannel^)browserProcess);
try
{
clientChannel->Open(); <-- FAILS
browser->ChannelFactory = channelFactory;
browser->BrowserProcess = browserProcess;
}
catch (Exception^)
{
}
}
With the error:
There was an error reading from the pipe: The pipe has been ended. (109, 0x6d)
Has anyone seen this issue before? I'm not sure how much this will help, but does anyone know if it's possible to enable WCF tracing with the CefSharp.BrowserSubProcess.exe. I have been trying this, but no luck so far.
In my web application, I have a custom configuration file which I want to monitor for changes and update the application settings immediately. So I am using IOptionsMonitor<T> to get this done. It works well.
As per the documentation the method that gets called when configuration file changed is wired up like below.
var data = _serviceProvider.GetRequiredService<IOptionsMonitor<MySettings>>();
data.OnChange(OnReaderSettingOptionsChanged);
Within the OnReaderSettingOptionsChanged() method, I do some validations and there is a need to throw an exception on an edge case so that application shouldn't continue.
The problem is when I throw the exception, I expect to see a error on browser (dev mode with details or normal error otherwise). But it's not showing because according to this exception gets fired in another thread.
So, is there another way for me to get this across to browser?
My main program is an ASP.Net Core Web API that has a third party library in a hosted service. The third party library is initializing fine but then it throws some errors sometime throughout its lifecycle.
It supplies a way of hooking into the object via an event and will let me know what the error is so that I can handle it but it still throws in the third party library..
Since I am handling the event myself, I want to completely ignore these errors that are occurring in this library. Is there anyway that I can do that?
I have already tried to add a global exception handler and the strange thing is, this exception handler never gets hit. The only way I can get the exception is to set my exception settings to break when CLR exceptions happen like in the picture above
This does not crash my program. For some reason, the program just hangs. When I turn off CLR exceptions in the "Break when thrown" window, then the program runs just fine. It is almost like visual studio is doing something special to handle these types of exceptions that a console version cannot do
The only way that I can seem to get a console version of this running, is attach a visual studio debugger to the process and when the exception is hit, press the green play button "Continue" in visual studio. Otherwise the application just seems to hang on the exception being thrown by the third party library.
The application will run fine as long as visual studio is attached and the CLR break exceptions are not checked
Does anyone know how to make sure that these types of exceptions do not hang the program when released?
Additional Info:
The third party library is a .NET Framework 4 library
The Asp.Net project is targetting "net5.0-windows"
The 3rd party class is probably using multi-threading
if it helps, this is how I am creating the third party class
Handling NullReferenceException in release code(Official advice)
It's usually better to avoid a NullReferenceException than to handle it after it occurs. Handling an exception can make your code harder to maintain and understand, and can sometimes introduce other bugs. A NullReferenceException is often a non-recoverable error. In these cases, letting the exception stop the app might be the best alternative.
However, there are many situations where handling the error can be useful:
1.Your app can ignore objects that are null. For example, if your app retrieves and processes records in a database, you might be able to ignore some number of bad records that result in null objects. Recording the bad data in a log file or in the application UI might be all you have to do.
2.You can recover from the exception. For example, a call to a web service that returns a reference type might return null if the connection is lost or the connection times out. You can attempt to reestablish the connection and try the call again.
3.You can restore the state of your app to a valid state. For example, you might be performing a multi-step task that requires you to save information to a data store before you call a method that throws a NullReferenceException. If the uninitialized object would corrupt the data record, you can remove the previous data before you close the app.
4.You want to report the exception. For example, if the error was caused by a mistake from the user of your app, you can generate a message to help them supply the correct information. You can also log information about the error to help you fix the problem. Some frameworks, like ASP.NET, have a high-level exception handler that captures all errors to that the app never crashes; in that case, logging the exception might be the only way you can know that it occurs.
So after days of research I've finally found an event to hook into to give you error messages from ANY source no matter how many level deep you go in threads.
AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
Hooking into this event it will allow you to see errors from every library and every thread. Simply place the above into you program.cs (or whatever startup file you have) and magically you will be flooded with all of the unknown errors from all of the 3rd party libraries you thought were once flawless.
private static void CurrentDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
{
Console.WriteLine(e.Exception.Message, e.Exception.StackTrace);
}
I've done so with the following method and low and behold. The third party library was trying to reference another project in an unsafe way and throwing an error. Since I didn't need this other project reference the built exe did not have a reference to this assembly because I had no direct reference to it in the project (darn smarty pants who need to optimize everything). I was able to run correctly because in my visual studio solution, I had a reference to this other project. So the third party library would pick up on it as soon as visual studio connected with the debugger through some sort of dark magic.
Anyways, I made a throw away object that used the project that was required and the issue was solved.
I really hope that this helps someone else and saves them the days it took me to find this.
I have a Windows service built upon ATL 7's CAtlServiceModuleT class. This service serves up COM objects that are used by various applications on the system, and these other applications naturally start getting errors if the service is stopped while they are still running.
I know that ATL DLLs solve this problem by returning S_OK in DllCanUnloadNow() if CComModule's GetLockCount() returns 0. That is, it checks to make sure no one is currently using any COM objects served up by the DLL. I want equivalent functionality in the service.
Here is what I've done in my override of CAtlServiceModuleT::OnStop():
void CMyServiceModule::OnStop()
{
if( GetLockCount() != 0 ) {
return;
}
BaseClass::OnStop();
}
Now, when the user attempts to Stop the service from the Services panel, they are presented with an error message:
Windows could not stop the XYZ service on Local Computer.
The service did not return an error. This could be an internal Windows error or an internal service error.
If the problem persists, contact your system administrator.
The Stop request is indeed refused, but it appears to put the service in a bad state. A second Stop request results in this error message:
Windows could not stop the XYZ service on Local Computer.
Error 1061: The service cannot accept control messages at this time.
Interestingly, the service does actually stop this time (although I'd rather it not, since there are still outstanding COM references).
I have two questions:
Is it considered bad practice for a service to refuse to stop when asked?
Is there a polite way to signify that the Stop request is being refused; one that doesn't put the Service into a bad state?
You can't do this. Once the SCM sends a SERVICE_CONTROL_STOP to your service, you have to stop.
If your other apps are also services, you can make them dependencies within the SCM. Of course, if the apps using this service are just regular applications that can't be used.
When ATL's lock count increments to 1, call SetServiceStatus() with the SERVICE_ACCEPT_STOP flag omitted in the SERVICE_STATUS::dwControlsAccepted field. Then you will not receive any SERVICE_CONTROL_STOP requests at all. Any attempt to stop the service will fail immediately. When ATL's lock count falls back to 0, call SetServiceStatus() again with the SERVICE_ACCEPT_STOP flag specified.
I just had to do this in 2 (older) ATL-based services, and it works well. Granted, I was unable to figure out the best way to override Lock() and Unlock() directly, so I just put a small loop inside my service that checks GetLockCount() at frequent intervals and calls SetServiceStatus() when needed.
In your constructor, update m_status.dwControlsAccepted removing SERVICE_ACCEPT_STOP. For instance:
CMyServiceModule::CMyServiceModule()
: ATL::CAtlServiceModuleT<CMyServiceModule, IDS_SERVICENAME>()
{
m_status.dw &= ~SERVICE_ACCEPT_STOP
}
I am writing a windows service that needs to be running 24/7. It is a pretty simple service that monitors a directory where files are dropped into and processes those files. I need to restart the service if an unhandled exception is thrown.
Is there a way for a service to restart itself in the event of an unhandled exception?
The Services applet has many different recovery features:
It can take different actions on the first, second, and subsequent failures:
Restart the service, after a configurable delay
Run a Program (passing command line parameters, possibly including the failure count)
Restart the Computer (after a configurable delay, and with a particular message being sent)
The program that runs should be able to look in the event log and see the reason for failure (especially if you log it), and should therefore be able to disable the service if the exception is one that is not recoverable.
And, of course, in the meantime, the service should be logging what's going on, which should enable any management tool to notify Operations of what's going on.
I agree that you should probably not configure "third and subsequent" to be "restart service", or you could wind up in a loop.
Have you tried using the Recovery tab of the Service entry - you can set rules for failures, including "Restart the Service" - by default this is on "No Action"
This is able to be done programatically if you wanted, this code was not written by me. I am posting the link to the Authors CodeProject page that contains the source / binaries. Below the link I have explained how I implemented the authors code.
http://www.codeproject.com/KB/install/sercviceinstallerext.aspx
Add a reference to the DLL.
Open ProjectInstaller.Designer.vb in notepad
In the InitializeComponent Sub
CHANGE
Me.ServiceProcessInstaller1 = New System.ServiceProcess.ServiceProcessInstaller
Me.ServiceInstaller1 = New System.ServiceProcess.ServiceInstaller
TO
Me.ServiceProcessInstaller1 = New System.ServiceProcess.ServiceProcessInstaller
Me.ServiceInstaller1 = New Verifide.ServiceUtils.ServiceInstallerEx
With the Friend Declarations in the ProjectInstaller.Designer.vb
CHANGE
Friend WithEvents ServiceProcessInstaller1 As System.ServiceProcess.ServiceProcessInstaller
Friend WithEvents ServiceInstaller1 As System.ServiceProcess.ServiceInstaller
TO
Friend WithEvents ServiceProcessInstaller1 As System.ServiceProcess.ServiceProcessInstaller
Friend WithEvents ServiceInstaller1 As Verifide.ServiceUtils.ServiceInstallerEx
CHANGE
Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceProcessInstaller1, Me.ServiceInstaller1})
TO
Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceInstaller1, Me.ServiceProcessInstaller1})
Import The Namespace On ProjectInstaller.vb
In ProjectInstaller.vb in the Public Sub New Function After Initialize component function has been called
ADD
'Set Reset Time Count - This Is 4 Days Before Count Is Reset
ServiceInstaller1.FailCountResetTime = 60 * 60 * 24 * 4
'ServiceInstaller1.FailRebootMsg = "Houston! We have a problem"
'Add Failure Actions
ServiceInstaller1.FailureActions.Add(New FailureAction(RecoverAction.Restart, 60000))
ServiceInstaller1.FailureActions.Add(New FailureAction(RecoverAction.Restart, 60000))
ServiceInstaller1.FailureActions.Add(New FailureAction(RecoverAction.None, 3000))
ServiceInstaller1.StartOnInstall = True
Build installer and install. Voila
Wrap your service code in a runner which can catch any errors and restart your service.
The best way is to wrap Try / Catch blocks around the methods in the service you can afford to let throw exceptions.
However, there may be serious exceptions thrown that should result in the service being stopped immediately. Don't ignore these! In these cases, handle the exception, log it, email it and then rethrow it. That way you will be informed that the exception has occurred and will know what went wrong. You can then fix the problem and re-start the service manually.
Just ignoring it could cause a major failure in your system which you would not know about. It could also be very expensive on CPU/RAM if the service stops then restarts then stops ad infinitum.
As suggested by "John Saunders" and "theGecko", you can monitor the service and restart it when it fails. The builtin Windows Service Recovery functionality will get you a long way, but if you find that you need some more advanced features (for example, CPU hogging and hang detection) then please check out Service Protector. It is designed to keep your important Windows Services operating 24x7.
Good luck!