2

I'm using a crappy third party library because unfortunately I have no choice. This library creates a bunch of threads internally when I call it, and occasionally throws a NullReferenceException on one of these threads. Is there any way for me to catch these exceptions even though I don't own the thread that throws them? I have no way to change the third party code.

As a simple example to show the problem:

public static void main()
{
    try
    {
        var crappyLib = new CrappyLibrary();
        crappyLib.DoCrappyThings();
    }
    catch
    {
        Console.WriteLine("This never happens");
    }
}

// I do not own the following code, I can't change it
public class CrappyLibrary
{
    public void DoCrappyThings()
    {
        var t = new Thread(DoWork);
        t.Start();
    }
    private void DoWork()
    {
        throw new ThisLibrarySucksException();
    }
}
ConditionRacer
  • 4,418
  • 6
  • 45
  • 67
  • Are you able to use a `try...catch` around the third party code your using? – Jason Evans Jun 15 '15 at 15:18
  • Yes, but the exception is not propagated to the calling thread. – ConditionRacer Jun 15 '15 at 15:19
  • Normally, in .NET web apps, you have en event in global.asax -> void Application_Error(object sender, EventArgs e) - where you can catch all errors ocurred in the application. Whitch type of application are you doing? – Coastpear Jun 15 '15 at 15:22
  • Try to handle the `Application.ThreadException` or `AppDomain.CurrentDomain.UnhandledException` event globally for your app – Jens Jun 15 '15 at 15:26
  • This has already been answered here: http://stackoverflow.com/questions/17298269/catching-exceptions-caused-in-different-threads – Lunyx Jun 15 '15 at 15:27
  • @OP: Can you tell us what you would do with the exception if you could catch it? Is your goal to log it? Or is your goal to ignore it to prevent the process from terminating? – sstan Jun 15 '15 at 15:32
  • @sstan The third part library connects to an MQ server. If it fails, I want to dispose everything and retry a certain number of times as it seems to be random and extremely flaky. This is also why the global unhandled exception handlers aren't useful. – ConditionRacer Jun 15 '15 at 15:41
  • 3
    The suggested threads do not answer the question, I'm interested in catching exceptions for THREADS I DO NOT OWN, therefor I cannot try catch the exception, it's executing on a stack that I have no access to. – ConditionRacer Jun 15 '15 at 15:44
  • @OP: I see. Still, I added an answer that may come in handy. But I'm not sure it addresses your specific goal. – sstan Jun 15 '15 at 15:46
  • 4
    This is NOT A DUPE because OP can't change the code used to start the thread – g3rv4 Jun 15 '15 at 16:04

3 Answers3

2

The thing worrying me most in the described case is abnormal thread termination inside that 3rd-party lib. Once a thread is throwing, you can't catch the exception via correct way because you're not the owner of that thread invocation (and it has no idea it should propagate the exception to you; unlike it happens in TPL, let say). So even if handling such exceptions via a global handler this could be incorrect way because the lib can appear in non-consistent state after any of such exceptions.

So the safe way here is to isolate the lib inside some scope and re-launch the scope after any exception. Let say, to load the lib into separate domain.

Yury Schkatula
  • 5,291
  • 2
  • 18
  • 42
  • I was trying to avoid having to sandbox this in another process, but it looks like it might be the only solution. I don't have any control over this library, but I have to use it for reasons I cannot go into and I'm having trouble getting support for this issue. I'm looking for workarounds to a bad situation. – ConditionRacer Jun 15 '15 at 15:47
  • 1
    @ConditionRacer, small correction: C# domains are not other processes, they're isolation levels embedded into .NET infrastructure so you don't need to worry about cross-app things. So particular app can have multiple domains as most of apps just use default domain at will. P.S. being an outsourcer for many years I feel your pain and understand the situation – Yury Schkatula Jun 16 '15 at 12:09
1

If your goal is to prevent early termination of your process because of these unhandled exceptions that are not under your control, then there exists the legacyUnhandledExceptionPolicy setting that you can add to your app.config that will prevent unhandled thread exceptions from terminating the whole process.

Obviously, the solution is not perfect, as unhandled exceptions can destabilize the state of the threads. But at least it's an option you can consider.

Please have a look at the documentation about this here to better understand the implications of turning on this setting.

Your app.config would have to look something like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <legacyUnhandledExceptionPolicy enabled="1"/>
  </runtime>
</configuration>

EDIT: Just a thought, but perhaps the above setting, in combination with adding an event handler for AppDomain.UnhandledException can help you with your need.

Using AppDomain.UnhandledException, you can detect the failure, so that you know when you need to trigger a retry, or whatever else it is that you need to do in these cases.

And the legacyUnhandledExceptionPolicy setting would still be useful to prevent the process from shuting down, thus giving you the opportunity to perform the retry.

sstan
  • 35,425
  • 6
  • 48
  • 66
0

I hope this is helpful https://msdn.microsoft.com/en-GB/library/system.windows.forms.application.threadexception.aspx

You can try something like that (it's from the article)

Application.ThreadException += new ThreadExceptionEventHandler  (ErrorHandlerForm.Form1_UIThreadException);

// Set the unhandled exception mode to force all Windows Forms errors to go through 
// our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

// Add the event handler for handling non-UI thread exceptions to the event. 
AppDomain.CurrentDomain.UnhandledException +=
    new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
  • 1
    The first two examples you have only work in Windows Forms applications... The third one lets you look at the error, but doesn't prevent the application from shutting down. – Ron Beyer Jun 15 '15 at 15:29
  • Unfortunately, I want to do more than just log the exception. I'm trying to recover and continue. – ConditionRacer Jun 15 '15 at 15:46