I want to know whether unhandled exception will make WCF service crash. I have written the following program which shows unhandled exception in a thread started by WCF service will make the whole WCF service crash.
My question is, I want to confirm whether unhandled exception in threads (started by WCF service) will make WCF crash? My confusion is I think WCF should be stable service which should not crash because of unhandled exception.
I am using VSTS 2008 + C# + .Net 3.5 to develop a self-hosted Windows Service based WCF service.
Here are the related parts of code,
namespace Foo
{
// NOTE: If you change the interface name "IService1" here, you must also update the reference to "IService1" in Web.config.
[ServiceContract]
public interface IFoo
{
[OperationContract]
string Submit(string request);
}
}
namespace Foo
{
// NOTE: If you change the class name "Service1" here, you must also update the reference to "Service1" in Web.config and in the associated .svc file.
public class FooImpl : IFoo
{
public string Submit(string request)
{
return String.Empty;
}
}
}
namespace Foo
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
ServiceHost host = new ServiceHost(typeof(FooImpl));
protected override void OnStart(string[] args)
{
host.Open();
// start a thread which will throw unhandled exception
Thread t = new Thread(Workerjob);
t.Start();
}
protected override void OnStop()
{
host.Close();
}
public static void Workerjob()
{
Thread.Sleep(5000);
throw new Exception("unhandled");
}
}
}
An unhandled exception on the service side will cause the channel (the connection between the client and the server) to "fault" - e.g. to be torn down.
From that point on, you cannot call from the client using the same proxy client object instance anymore - you'll have to re-create the proxy client.
Your best bet is to handle all error on the server side whenever possible. Check out the IErrorHandler interface, which you should implement on your service implementation class, to turn all unhandled .NET exceptions into either SOAP faults (which will NOT cause the channel to fault), or to report / swallow them entirely.
Marc
Yes, an unhandled exception in a thread will take the process down.
This process will crash:
static void Main(string[] args)
{
Thread t = new Thread(() =>
{
throw new NullReferenceException();
});
t.Start();
Console.ReadKey();
}
This one will not:
static void Main(string[] args)
{
Thread t = new Thread(() =>
{
try
{
throw new NullReferenceException();
}
catch (Exception exception)
{
Console.WriteLine(exception.ToString());
}
});
t.Start();
Console.ReadKey();
}
The default behavior of the WCF runtime is to swallow all but a few types exceptions. So if your code throws an exception down the stack to the WCF runtime (such as if you throw from a WCF operation), it will NOT crash the app (unless it is deemed a "fatal" exception, such as OOM, SEHException, etc.). If the exception is not part of the operation's fault contract, then the channel will be faulted, otherwise not.
If the WCF runtime is not under your code on the stack, then the exception /will/ crash the process.
This is similar to the ASP.NET runtime.
If you would like to screen for exceptions flying out of WCF operations in a general way, I recommend using the IOperationInvoker interface. You can also use IErrorHandler, but your IErrorHandler implementation will be notified of exceptions other than those thrown from "user code" (WCF operations), such as SocketAbortedExceptions on WCF internal I/O threads, which are probably not interesting to you.
If you don't handle an exception it gets passed on the operating system and it will respond by killing what ever application caused the exception.
Why don't you just add a try/catch to handle the exceptions so that your service is not killed ?
If you don't have proper error handling it will make the program crash. Its good practise to put a
try{//do something
}
catch{ //handle errors
}
finally{//final clean up
}
block in your code to make sure that if it does throw an exception is to handle it gracefully. examples at http://msdn.microsoft.com/en-us/library/fk6t46tz(VS.71).aspx
You can make use of FaultException to communicate errors to the client side and keep the logic in the service.
Check this example, hope it helps you.
Related
I'm hosting WCF as Widnows Service but I have a problem with handling Faulted state of WCF channel. Faulted event on ServiceHost never rise up.
Hosting application:
protected override void OnStart(string[] args)
{
_serviceHost = new ServiceHost(typeof(WCF_FaultTest.Service1));
_serviceHost.Faulted += _serviceHost_Faulted;
_serviceHost.Open();
}
void _serviceHost_Faulted(object sender, EventArgs e)
{
// never raise up..
}
Faulted state I try to simulate like this:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
public class Service1 : IService1
{
public string GetFault()
{
throw new Exception("Should went to fault..");
}
Do I using it correctly? Thank you.
You are using more than one CommunicationObject. When you throw the exception in your service implementation the channel is faulted, but the host it is not. The ServiceHost.Faulted event does not apply in this case.
One thing to remember is that once a CommunicationObject enters the faulted state, it can no longer be used. The only thing to do with a faulted CommunicationObject is to close/abort. After your service throws the exception, if you create a new channel you can still call the service. Therefore the service is not faulted.
From an architecture point of view, a service host event is not the "right" place to implement error handling. In general you want error processing to be part of the service configuration. For example error handling in a ServiceHost event doesn't easily move to IIS hosting. Your comment makes it sound like IErrorHandler didn't meet your requirements. What requirement are you trying to implement?
Is there any way to capture and log exceptions thrown from a WCF service's constructor?
Creating a custom IEndpointBehavior with a custom IErrorHandler seems to catch all exceptions except those thrown during service construction. (Please correct me if I'm wrong.)
I can see from the HTTP response that this situation eventually generates a System.ServiceModel.ServiceActivationException, but it would be helpful if I could log out the details from the original exception.
You can use WCF tracing
http://msdn.microsoft.com/en-us/library/ms733025.aspx
You can turn it on in the service configuration so no need to instrument your code.
You will need to create a class to log the exception, initialize it in the constructor and call it when an exception is caught. Below is a very simple example:
public class MyWcfService : IMyWcfService
{
private readonly IExceptionLogger_ exceptionLogger;
public MyWcfService()
{
// Initialize dependencies
_exceptionLogger = new ExceptionLogger();
try
{
// Code here that throws an exception
}
catch (Exception ex)
{
_exceptionLogger.LogException(ex);
}
} // end constructor
// Other methods here
} // end class
protected override void OnStart(string[] args)
{
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Thread.Sleep(10000);
throw new Exception();
}
void CurrentDomain_UnhandledException(object sender,
UnhandledExceptionEventArgs e)
{
}
I attached a debugger to the above code in my windows service, setting a breakpoint in CurrentDomain_UnhandledException, but it was never hit. The exception pops up saying that it is unhandled, and then the service stops. I even tried putting some code in the event handler, in case it was getting optimized away.
Is this not the proper way to set up unhandled exception handling in a windows service?
The reason that the UnhandledException event on the current AppDomain does not fire is how services are executed.
User sends a Start command from the Windows Service Control Manager (SCM).
The command is received by the framework's ServiceBase implementation and dispatched to the OnStart method.
The OnStart method is called.
Any exception which is thrown by OnStart is handled in the base class, logged to the Event Log, and translated into an error status code returned to the SCM. So the exception never propagates to the AppDomain's unhandled exception handler.
I think you would find that an unhandled exception thrown from a worker thread in your service would be caught by the AppDomain's unhandled exception handler.
In a Windows Service you do NOT want to be running much code in the OnStart method. All you want there is the code to launch your service thread and then return.
If you do that you can handle exceptions that happen in your service thread just fine.
e.g.
public static void Start()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(currentDomain_UnhandledException);
running = true;
ThreadStart ts = new ThreadStart(ServiceThreadBody);
thread = new Thread(ts);
thread.Name = "ServiceThread";
thread.Priority = ThreadPriority.BelowNormal;
thread.Start();
}
When I was working on my own Windows Service, it was stoping itself oddly enough. I thought it was because of unhanded exception. At the moment I am catching unhanded exceptions on text file. First of all you have to create new file ServiceLog.txt on C locations due to logging excaptions on text file. With below coding I got all unhanded exceptions with them line numbers.
using System.Security.Permissions;
using System.IO;
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
protected override void OnStart(string[] args)
{ AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
...
Your codes...
....
}
void MyHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
WriteToFile("Simple Service Error on: {0} " + e.Message + e.StackTrace);
}
private void WriteToFile(string text)
{
string path = "C:\\ServiceLog.txt";
using (StreamWriter writer = new StreamWriter(path, true))
{
writer.WriteLine(string.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")));
writer.Close();
}
}
Know this thread is a bit old, but thought it would be useful to add some comments based on personal experience developing Windows services in .NET. The best approach is to avoid developing under the Service Control Manager as much as you can - for this you need a simple harness that mimics the way services get started - something that can create an instance of your service class (that you already derived from ServiceBase) and call your OnStart, OnStop etc methods. This harness can be a console app or a Windows app as you desire.
This is pretty much the only way I have found of debugging service start-up issues in .NET - the interaction between your code, Visual Studio and the real Service Control Manager just makes the process impossible otherwise.
HTH.
Just curious, what are you trying to accomplish: avoiding service crashing, or reporting errors?
For reporting, I think your best bet is to add top-level try/catch statements. You can try to log them to the Windows event log and/or a log file.
You can also set the ExitCode property to a non-zero value until you successfully stop the service. If the system administrator starts your service from the Services control panel, and your service stops suddenly with a non-zero exit code, Windows can show an error message with the description of the error.
I am currently using a C# .NET Service in our client program. As part of the server design, several custom made exceptions are thrown to indicate specific errors (as in any normal desktop program).
The problem is that the Web Service catches these errors and serializes them into a FaultException, with the actual exception (like NoRoomsAvailableException) written in the Message field.
My question is whether there is a best practice for handling these errors. We have just begun working on this, and we would probably do some text pattern matching to pull out the exception type and error message, but it seems like a hacky way to do it, so any "clean" way of doing it would be much appreciated.
The proper way would be to define fault contracts. For example in your web service you could do the following:
[DataContract]
public class NoRoomsAvailableFaultContract
{
[DataMember]
public string Message { get; set; }
}
Next you declare this contract for a given service operation
[ServiceContract]
public interface IMyServiceContract
{
[OperationContract]
[FaultContract(typeof(NoRoomsAvailableFaultContract))]
void MyOperation();
}
And you implement it like so:
public class MyService : IMyServiceContract
{
public void MyOperation()
{
if (somethingWentWrong)
{
var faultContract = new NoRoomsAvailableFaultContract()
{
Message = "ERROR MESSAGE"
};
throw new FaultException<NoRoomsAvailableFaultContract>(faultContract);
}
}
}
In this case the NoRoomsAvailableFaultContract will be exposed in the WSDL and svcutil.exe could generate a proxy class. Then you could catch this exception:
try
{
myServiceProxy.MyOperation();
}
catch (FaultException<NoRoomsAvailableFaultContract> ex)
{
Console.WriteLine(ex.Message);
}
darin has the correct answer. I'll only say explicitly what he implies: web services do not pass exceptions. They return SOAP Faults. If you define your faults properly, as he does, then you get to throw FaultException<fault>. This will become a SOAP Fault with fault in the detail element. In the case of a .NET client, this will then be turned into a FaultException<fault>, which you can catch.
Other platforms may handle this somewhat differently. I've seen IBM's Rational Web Developer generate Java proxy code that creates a separate exception for each declared fault. That was a version before Java generics, so maybe by now it does the same thing as .NET does.
I have a WCF Service that should not enter the faulted state. If there's an exception, it should be logged and the service should continue uninterrupted. The service has a one-way operation contract and is reading messages from an MSMQ.
My problems are twofold:
The service appears to be swallowing
an exception/fault so I am unable to
debug it. How do I get the service
to expose the exception so that I
can log or handle it?
The service is
entering into a faulted state after
this exception is swallowed. How do
I prevent the service from entering
into a faulted state?
The official documentation on how to handle Faults is here:
Handling Exceptions and
Faults
Understanding State
Changes
with the main page being at Channel Model Overview
There's a nice state diagram showing how things happen:
Most, if not all exceptions can be seen in the WCF Trace (Configuring Tracing) and the trace is best viewed with the Service Trace Viewer.
Obviously, this is not something you should have running all day in a production environment, but it helps in troubleshooting anyway.
Apart from that, note that oneways may not run as a true "fire and forget" depending on the SessionMode you use. If you have your service configured for SessionMode.Allowed or even SessionMode.Required, the oneway operation will run as if it was not oneway at all (this can be observed when using oneways over the netTcpBinding). To be frank, however, I don't know if that changes the type of exceptions you can get, or when you get them. However, in any case, you should get an exception if the request could not be send at all. AFAIK, the oneway "ends" when it is successfully enqued on the server side. So there is some place for (WCF framework related) exceptions until then (serialization/deserialization comes to mind).
Then, such framework related exceptions are best seen (even an IErrorHandler doesn't get them all due to the fact when it is called in the request/response-flow) using the above mentioned trace / traceviewer.
Exceptions will fault the proxy. You can't AFAIK do much about that: don't cause exceptions ;-p
I'm a little surprised that one-way is still causing a problem, but for swallowing in general, there are 3 aspects:
are you throwing faults? or exceptions? it matters (and should be "faults")
as a hack, you can enable debug exception messages - but turn it off please!!!
are you "using" the service object? I've just blogged on this exact subject... basically, your "using" can swallow the exception.
3 options:
don't use "using"
subclass the proxy and override Dispose()
wrap it, as per the blog
Usually the WCF service is hosted in a ServiceHost, if the WCF-Service fails then the only option is to kill the WCF service and start a new one.
The ServiceHost has an event trigger "Faulted" that is activated when the WCF Service fails:
ServiceHost host = new ServiceHost(new Service.MyService());
host.Faulted += new EventHandler(host_faulted);
host.Open();
It is possible to get the exception causing the fault, but it requires a bit more work:
public class ErrorHandler : IErrorHandler
{
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
}
public bool HandleError(Exception error)
{
Console.WriteLine("exception");
return false;
}
}
public class ErrorServiceBehavior : IServiceBehavior
{
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
ErrorHandler handler = new ErrorHandler();
foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
dispatcher.ErrorHandlers.Add(handler);
}
}
}
ServiceHost host = new ServiceHost(new Service.MyService());
host.Faulted += new EventHandler(host_faulted);
host.Description.Behaviors.Add(new ErrorServiceBehavior());
host.Open();
Credits http://www.haveyougotwoods.ca/2009/06/24/creating-a-global-error-handler-in-wcf
I had an issue where the Channel remained in a faulted state after a ReceiveTimeout exception. This would cause the service to be rendered unusable by any subsequent connections.
The fix for recovering the service from the faulted state for me was to handle the Faulted event of the communication channel:
channelFactory = new ChannelFactory<IService>(endpoint);
channelFactory.Faulted += OnChannelFaulted;
var channel = channelFactory.CreateChannel();
Then define OnChannelFaulted:
void OnChannelFaulted(object sender, EventArgs e)
{
channelFactory.Abort();
}
Note: I am running the WCF config via code versus using bindings in the Web.config's.
About 2)...
The trick is that you should use "using" and should always call Abort() on the proxy that threw an exception. The article WCF Gotcha explains it all.
We use service class inspired by that article that wraps service calls. This is sample code from my project:
ServiceHelper<CodeListServiceClient, CodeListService.CodeListService>.Use(
proxy => seasonCodeBindingSource.DataSource = proxy.GetSeasonCodes(brandID);
);
And this is the code of ServiceHelper, slightly modified from the article. So far it has served us really well.
using System;
using System.ServiceModel;
namespace Sportina.EnterpriseSystem.Client.Framework.Helpers
{
public delegate void UseServiceDelegate<TServiceProxy>(TServiceProxy proxy);
public static class ServiceHelper<TServiceClient, TServiceInterface> where TServiceClient : ClientBase<TServiceInterface>, new() where TServiceInterface : class
{
public static void Use(UseServiceDelegate<TServiceClient> codeBlock)
{
TServiceClient proxy = null;
bool success = false;
try
{
proxy = new TServiceClient();
codeBlock(proxy);
proxy.Close();
success = true;
}
catch (Exception ex)
{
Common.Logger.Log.Fatal("Service error: " + ex);
throw;
}
finally
{
if (!success && proxy != null)
proxy.Abort();
}
}
}
}