I am using VSTS 2008 + C# + .Net 3.5 to develop a Windows Service application. The code is very simple below, and I find when File.Copy throws exception (e.g. path not valid, no permission, etc.), the service will crash and pop-up a dialog to let me debug. My confusion is, I think unhandled exception of a thread created by a Windows service will never make the service crash. Why my service crashes and the debug dialog pop-up?
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Thread t = new Thread (WriteF);
t.Start();
}
static void WriteF() {
File.Copy("dummy.txt", #"\\somelocation\dummy.txt");
}
protected override void OnStop()
{
}
}
I think unhandled exception of a thread created by a Windows service will never make the service crash
Your assumption is simply wrong. Unhandled exceptions in a Windows service will cause it to crash. The debug dialog appears because there is a debugger configured on your system. From .NET 2.0 onwards, an unhandled exception on any thread shuts down the whole application. Just because you're using a thread doesn't mean exceptions in the thread will magically go away.
Your file copy operation is throwing an exception which is not being caught. Simple as that. The service will fail unless you wrap the File.Copy operation in a try catch block. It does not matter that the operation is being performed on a background thread. I would also suggest adding some logging otherwise you won't discover why it's failing.
You start a new thread for running the code in WriteF. If this code fails with an exception, the runtime will try to find an exception handler by unwinding the stack for that particular thread. If it fails in locating a handler, the runtime has no option but the report an unhandled exception and thus the process is terminated. Remember exception handling is per thread. This is not a Windows Service issue.
Related
We are running an NServiceBus-based service, using the NServiceBus.Host.exe host process.
Twice in production during the last few months the Windows Service has suddenly stopped, leaving the following event in the Application Event Log:
Application: NServiceBus.Host.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.InvalidOperationException
Stack:
at System.Transactions.TransactionState.ChangeStatePromotedPhase0(System.Transactions.InternalTransaction)
at System.Transactions.Phase0VolatileDemultiplexer.InternalPrepare()
at System.Transactions.VolatileDemultiplexer.PoolablePrepare(System.Object)
at System.Transactions.Oletx.OletxVolatileEnlistment.Prepare(System.Transactions.Oletx.OletxVolatileEnlistmentContainer)
at System.Transactions.Oletx.OletxPhase0VolatileEnlistmentContainer.Phase0Request(Boolean)
at System.Transactions.Oletx.OletxTransactionManager.ShimNotificationCallback(System.Object, Boolean)
at System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(System.Object, Boolean)
We got this error during a period with some minutes of network instability (e.g. lots of timeouts against the database, which are visible in our log4net log files)
Any ideas as to what is failing here?
We see no fatal errors in our log4net logfiles.
Versions:
Windows Server 2008 R2
.NET Framework 4.5.2
NServiceBus 4.7.5
NHibernate 3.3.3.4001 (used for saga, subscription and timeout persister)
SQL Server 2012
It seems the behavior you see is related to how NHibernate handles the TransactionCompleted event. This questions is also somehow related to this question.
The AdoNetWithDistributedTransactionFactory registers an anonymous delegate on the TransactionCompleted event. This event gets fired on a background thread by using ThreadPool.QueueUserWorkItem. If that operation throws an exception due to connectivity issues with your database server (i.ex. due to a network partition) this exception gets raised as an unobserved exception on the AppDomain. UnhandledExceptions tear down the AppDomain and therefore also the NServiceBus.Host.
The best possible workaround for that would be to register an UnhandledException handler on the current AppDomain like the following
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException
private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
LogManager.GetLogger(typeof(AppDomain)).Fatal(“Unhandled exception”, e.ExceptionObject as Exception);
}
More information see
When this fixed the intermediate problem it would make sense to find the root cause of the connection issues with your database server in combination with NHibernate
I have these lines in my App.xaml.cs, to globally catch the exceptions:
this.Dispatcher.UnhandledException += new
DispatcherUnhandledExceptionEventHandler(
Current_DispatcherUnhandledException);
AppDomain.CurrentDomain.UnhandledException += new
UnhandledExceptionEventHandler(
CurrentDomain_UnhandledException);
Application.Current.DispatcherUnhandledException += new
DispatcherUnhandledExceptionEventHandler(
Current_DispatcherUnhandledException);
Most exceptions can be caught and a log file will be generated so that I know what is causing the error. But on my customer's PC (only windows 8 has
this problem), the WPF application sometimes crashed but I was not able to get the exception log, means the exception handlers above was not called.
Is there any handler I can set to catch exception? Or is there any log collector/reader like android DDMS for Windows/WPF app?
Thank you!
Since .NET 4.0 you could try and HandleProcessCorruptedStateExceptionsAttribute This attribute allows you to handle exceptions that since .Net 4 terminate the process. This is rather dangerous as you are allowing a process to continue (handle the exception) even when its memory has become corrupted.
In general: do not trust the application after catching such an exception. Log the exception and stop the application. Only when you know what is causing the exception and you are sure the application can recover you could apply this attribute to a method and make it resume normal execution.
I have the following code in my application that is running after an unhandled exception:
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var exception = e.ExceptionObject as Exception;
if (exception != null) MessageBox.Show(exception.Message + " - " + exception.StackTrace);
}
but even if i catch unhandled exception my windows mobile application close. How to prevent closing application when i catch unhandled exception. I never want to close my app. I want to open Login form in this scenario or anything else not close app.
So what i want is to prevent closing application from unhandled exception like network is down,...
I can not use try catch in every code ....
Any idea how to prevent closing app when network is down or any other unhandled exceptions?
You don't. When you get an AppDomain unhandled exception, your app is no longer in a stable state. Where exactly would you resume to? When you've gotten to that point, your only option, with good reason, is to exit. You could reasonably schedule yourself to run again to make sure the app comes back, but a far better idea is to actually handle the exception at its source and prevent it from being an UnhandledException.
In your app.config add the following element
<runtime>
<!-- the following setting prevents the host from closing when an unhandled exception is thrown -->
<legacyUnhandledExceptionPolicy enabled="1" />
</runtime>
You can, and you should use try...catch and handle the exceptions in every situation where an exception might occur. (In languages like Java you can't even compile your code until you catch every exception that the called function might throw or declare explicitly that this particular function won't catch it, so the one that calls it should do it.)
If you want to minimize the cases where you use try...catch some bad situations can be prevented with testing if the necessary conditions are met so you won't even call a function that is known for throwing a particular exception. Like calling
if (myByteArray != null)
{
myIPAddress = new IPAddress(myByteArray);
}
because this way the IPAddress constructor won't throw an ArgumentNullException.
However in most of the cases this can't be done, especially with networking, because you can't predict if the cable will be cut, the signal will be lost, the database server will crush, etc. in the middle of the transaction. So you should try...catch every time you connect to the network or send data to or receive data from a connection.
AppDomain.CurrentDomain.UnhandledException fires on any unhandled exception on
any thread, but since CLR 2.0, the CLR forces application shutdown after your event
handler completes. However, you can prevent shutdown by adding the following to
your application configuration file:
<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="1" />
</runtime>
</configuration>
I think you need to use Application.ThreadException
When you subscribe to Application.ThreadException, unhandled exceptions wont hit the UnhandledException and the app will keep running.
My asp.net application gives an exception once in a while as a result application pool stopped. and it needs to be started manually.
Does anyone know how to trace it, how to find what cause the problem?
I don't see any errors in Event Viewer.
In IIS 7.0, events (configurable) and exceptions (always) are logged to the Windows event log when an application pool recycles.
Sccot Guthrie's round-up of Tess's related posts is great:
Outstanding Blog for Learning how to Debug ASP.NET App Issues (Memory Leaks, Crashes, Deadlocks, etc)
ASP.NET 2.0 Crash case study: Unhandled exceptions
Try putting an Application_Error method on Global.asax.cs like this:
protected void Application_Error(object sender, EventArgs e)
{
// Get the exception object.
Exception exception = Server.GetLastError();
_Log.Error(exception.Message, exception);
// Clear the error from the server
Server.ClearError();
}
The _Log line assumes you're using log4net or some other logging framework but you could do whatever you want with the error.
PS - There's some misinformation in some of the other comments. But I don't have enough rep to comment on them. All IIS / WCF web service apps that I've written will terminate if any thread has an unhandled exception. I can't speak to whether that's true of ASP.Net apps as well.
Are you absolutely certain your application pool is stopping due to an error? There are many reasons the application pool can stop. Unless configured otherwise by default it will stop if inactive after a set ammount of time. I think about 20 minutes.
Quick summary with what I now know
I've got an EventWaitHandle that I created and then closed. When I try to re-create it with this ctor, an "Access to the path ... is denied" exception is thrown. This exception is rare, most of the times it just re-creates the EventWaitHandle just fine. With the answer posted below (by me), I'm able to successfully call EventWaitHandle.OpenExisting and continue on in the case that an exception was thrown, however, the ctor for EventWaitHandle should have done this for me, right? Isn't that what the out parameter, createdNew is for?
Initial question
I've got the following architecture, a windows service and a web service on the same server. The web service tells the windows service that it has to do work by opening and setting the wait handle that the windows service is waiting on.
Normally everything is flawless and I'm able to start / stop the windows service without any issue popping up. However, some times when I stop the web service and then start it up again, it will be completely unable to create the wait handle, breaking the whole architecture.
I specifically need to find out what is breaking the event wait handle and stop it. When the wait handle "breaks", I have to reboot windows before it will function properly again and thats obviously not ideal.
UPDATE: Exception thrown & Log of Issue
I rebooted the windows service while the web service was doing work in hopes of causing the issue and it did! Some of the class names have been censored for corporate anonymity
12:00:41,250 [7] - Stopping execution due to a ThreadAbortException
System.Threading.ThreadAbortException: Thread was being aborted.
at System.Threading.Thread.SleepInternal(Int32 millisecondsTimeout)
at OurCompany.OurProduct.MyClass.MyClassCore.MonitorRequests()
12:00:41,328 [7] - Closing Event Wait Handle
12:00:41,328 [7] - Finally block reached
12:00:42,781 [6] - Application Start
12:00:43,031 [6] - Creating EventWaitHandle: Global\OurCompany.OurProduct.MyClass.EventWaitHandle
12:00:43,031 [6] - Creating EventWaitHandle with the security entity name of : Everyone
12:00:43,078 [6] - Unhandled Exception
System.UnauthorizedAccessException: Access to the path 'Global\OurCompany.OurProduct.MyClass.EventWaitHandle' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.Threading.EventWaitHandle..ctor(Boolean initialState, EventResetMode mode, String name, Boolean& createdNew, EventWaitHandleSecurity eventSecurity)
at OurCompany.OurProduct.MyClassLibrary.EventWaitHandleFactory.GetNewWaitHandle(String handleName, String securityEntityName, Boolean& created)
at OurCompany.OurProduct.MyClassLibrary.EventWaitHandleFactory.GetNewEventWaitHandle()
at OurCompany.OurProduct.MyClass.MyClassCore..ctor()
Rough timeline:
11:53:09,937: The last thread on the web service to open that existing wait handle, COMPLETED its work (as in terminated connection with the client)
12:00:30,234: The web service gets a new connection, not yet using the wait handle. The thread ID for this connection is the same as the thread ID for the last connection at 11:53
12:00:41,250: The windows service stops
12:00:42,781: The windows service starts up
12:00:43,078: The windows service finished crashing
12:00:50,234: The web service was actually able to open the wait handle call Set() on it without any exception thrown etc.
12:02:00,000: I tried rebooting the windows service, same exception
12:36:57,328: After arbitrarily waiting 36 minutes, I was able to start the windows service up without a full system reboot.
Windows Service Code
Initialization:
// I ran into security issues so I open the global EWH
// and grant access to Everyone
var ewhSecurity = new EventWaitHandleSecurity();
ewhSecurity.AddAccessRule(
new EventWaitHandleAccessRule(
"Everyone",
EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify,
AccessControlType.Allow));
this.ewh = new EventWaitHandle(
false,
EventResetMode.AutoReset,
#"Global\OurCompany.OurProduct.MyClass.EventWaitHandle",
out created,
ewhSecurity);
// the variable "created" is logged
Utilization:
// wait until the web service tells us to loop again
this.ewh.WaitOne();
Disposal / closing:
try
{
while (true)
{
// entire service logic here
}
}
catch (Exception e)
{
// should this be in a finally, instead?
if (this.ewh != null)
{
this.ewh.Close();
}
}
Web Service Code
Initialization:
// NOTE: the wait handle is a member variable on the web service
this.existing_ewh = EventWaitHandle.OpenExisting(
#"Global\OurCompany.OurProduct.MyClass.EventWaitHandle");
Utilization:
// wake up the windows service
this.existing_ewh.Set();
Since the EventWaitHandle is a member variable on the web service, I don't have any code that specifically closes it. Actually, the only code that interacts with the EventWaitHandle on the web service is posted above.
Looking back, I should probably have put the Close() that is in the catch block, in a finally block instead. I probably should have done the same for the web service but I didn't think that it was needed.
At any rate, can anyone see if I'm doing anything specifically wrong? Is it crucially important to put the close statements within a finally block? Do I need to manually control the Close() of the existing_ewh on the web service?
Also, I know this is a slightly complex issue so let me know if you need any additional info, I'll be monitoring it closely and add any needed information or explanations.
Reference material
EventWaitHandleSecurity Class
EventWaitHandleAccessRule Class
EventWaitHandle Class
In the code that creates the wait handle on the windows service, if it fails (as in access denied), you could try to "open an existing wait handle" via
EventWaitHandle.OpenExisting(
#"Global\OurCompany.OurProduct.MyClass.EventWaitHandle",
EventWaitHandleRights.Synchronize | EventWaitHandleRights.Modify);
Though, I'm not entirely sure if the behaviour would stay the same at that point.
Note: I'd appreciate feedback. Its a potential answer so I'm answering my own question, again, plenty of comments are quite welcome!
Note 2: Amazingly, applying EventWaitHandleRights.FullControl instead of the above flags (Synchronize + Modify) doesn't work well. You must use the sample above.
MSDN says:
UnauthorizedAccessException - The named event exists and has access control security, but the user does not have EventWaitHandleRights.FullControl.
and
The caller has full control over the newly created EventWaitHandle object even if eventSecurity denies or fails to grant some access rights to the current user.
Your service has no rights to get the existing event via EventWaitHandle constructor. (EventWaitHandleRights.FullControl is not specified. And your named event exists while it has opened handles on it.) You can open the existing event using EventWaitHandle.OpenExisting.