Home All Groups Group Topic Archive Search About

Preventing Exceptions from bringing down app

Author
18 Mar 2006 3:03 AM
Michael Bray
I'm writing a library to support provide plugin capability to my
applications.  It does this by loading DLL's into a new AppDomain for each
plugin that is loaded.  Now obviously when I write a plugin, I can make
sure that my plugins don't throw any exceptions.  But I certainly can't
guarantee that other people writing plugins won't throw an exception.  The
problem is that if one of these other plugins throws an exception, it
brings down the entire application.

Is there anything I can do to prevent Exceptions in other AppDomains from
bringing down the entire app, when I don't own the code that is running in
that AppDomain?  I thought I would be able to use
AppDomain.UnhandledException, but as is pointed out in the link below, this
is only a "notification" not a "handler".

UnhandledException is not a handler: (watch the wrap)
http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx?
feedbackId=FDBK21092

-mdb

Author
18 Mar 2006 1:17 PM
Kevin Spencer
Without going into a lot of detail, here's an example. Modify it any way you
need to:

// Setup unhandled exception handlers
AppDomain.CurrentDomain.UnhandledException += // CLR
   new UnhandledExceptionEventHandler(OnUnhandledException);

Application.ThreadException += // Windows Forms
   new System.Threading.ThreadExceptionEventHandler(
    OnGuiUnhandedException);

// CLR unhandled exception
private static void OnUnhandledException(Object sender,
   UnhandledExceptionEventArgs e)
{
HandleUnhandledException(e.ExceptionObject);
}

// Windows Forms unhandled exception
private static void OnGuiUnhandedException(Object sender,
   ThreadExceptionEventArgs e)
{
HandleUnhandledException(e.Exception);
}

static void HandleUnhandledException(Object o)
{
Exception e = o as Exception;

if (e != null)
{
// Report System.Exception info
Debug.WriteLine("Exception = " + e.GetType());
Debug.WriteLine("Message = " + e.Message);
Debug.WriteLine("FullText = " + e.ToString());
Utilities.HandleError(e); // My own method that simply logs the exception
details
}
else
{
// Report exception Object info
Debug.WriteLine("Exception = " + o.GetType());
Debug.WriteLine("FullText = " + o.ToString());
Utilities.LogError("Exception: " + o.GetType().ToString() +
"\r\nFullText: " + o.ToString()); // My own method that simply logs the
exception details
}

MessageBox.Show("An unhandled exception occurred " +
   "and the application is shutting down.");
Environment.Exit(1); // Shutting down

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer

Presuming that God is "only an idea" -
Ideas exist.
Therefore, God exists.

Show quote
"Michael Bray" <mbray@makeDIntoDot_ctiusaDcom> wrote in message
news:Xns9789E05FC9236mbrayctiusacom@207.46.248.16...
> I'm writing a library to support provide plugin capability to my
> applications.  It does this by loading DLL's into a new AppDomain for each
> plugin that is loaded.  Now obviously when I write a plugin, I can make
> sure that my plugins don't throw any exceptions.  But I certainly can't
> guarantee that other people writing plugins won't throw an exception.  The
> problem is that if one of these other plugins throws an exception, it
> brings down the entire application.
>
> Is there anything I can do to prevent Exceptions in other AppDomains from
> bringing down the entire app, when I don't own the code that is running in
> that AppDomain?  I thought I would be able to use
> AppDomain.UnhandledException, but as is pointed out in the link below,
> this
> is only a "notification" not a "handler".
>
> UnhandledException is not a handler: (watch the wrap)
> http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx?
> feedbackId=FDBK21092
>
> -mdb
Author
18 Mar 2006 2:08 PM
Michael Bray
"Kevin Spencer" <kevin@DIESPAMMERSDIEtakempis.com> wrote in
news:OV0TO5oSGHA.336@TK2MSFTNGP12.phx.gbl:

> Without going into a lot of detail, here's an example. Modify it any
> way you need to:
>
> // Setup unhandled exception handlers
> AppDomain.CurrentDomain.UnhandledException += // CLR
>    new UnhandledExceptionEventHandler(OnUnhandledException);
>
> Application.ThreadException += // Windows Forms
>    new System.Threading.ThreadExceptionEventHandler(
>     OnGuiUnhandedException);

I've already tried using AppDomain.CurrentDomain.UnhandledException as well
as Application.ThreadException.  Neither one of them prevents the exception
from shutting the application down.  Sure I can capture the event and say
"Hey...  This plugin just caused an exception".  But I can't prevent that
exception from killing the application.  That's what I'm really trying to
get, so I can unload that faulty AppDomain but allow my program (and any
other plugins in other AppDomains) to continue working.

-mdb
Author
18 Mar 2006 4:16 PM
Kevin Spencer
Are these DLLs .Net assemblies? Can you provide more information about how
they interact with your application?

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer

Presuming that God is "only an idea" -
Ideas exist.
Therefore, God exists.

Show quote
"Michael Bray" <mbray@makeDIntoDot_ctiusaDcom> wrote in message
news:Xns978A5CF1E3493mbrayctiusacom@207.46.248.16...
> "Kevin Spencer" <kevin@DIESPAMMERSDIEtakempis.com> wrote in
> news:OV0TO5oSGHA.336@TK2MSFTNGP12.phx.gbl:
>
>> Without going into a lot of detail, here's an example. Modify it any
>> way you need to:
>>
>> // Setup unhandled exception handlers
>> AppDomain.CurrentDomain.UnhandledException += // CLR
>>    new UnhandledExceptionEventHandler(OnUnhandledException);
>>
>> Application.ThreadException += // Windows Forms
>>    new System.Threading.ThreadExceptionEventHandler(
>>     OnGuiUnhandedException);
>
> I've already tried using AppDomain.CurrentDomain.UnhandledException as
> well
> as Application.ThreadException.  Neither one of them prevents the
> exception
> from shutting the application down.  Sure I can capture the event and say
> "Hey...  This plugin just caused an exception".  But I can't prevent that
> exception from killing the application.  That's what I'm really trying to
> get, so I can unload that faulty AppDomain but allow my program (and any
> other plugins in other AppDomains) to continue working.
>
> -mdb
>
Author
18 Mar 2006 6:15 PM
Michael Bray
"Kevin Spencer" <kevin@DIESPAMMERSDIEtakempis.com> wrote in
news:evHlRdqSGHA.3192@TK2MSFTNGP09.phx.gbl:

> Are these DLLs .Net assemblies? Can you provide more information about
> how they interact with your application?
>

Better than that - I'll package up the Solution so you can see for
yourself.  I've posted it at

http://users.ctinet.net/mbray/PluginTest.zip

The program is 'PluginTest.exe'.  When it loads up, click the main menu
item called 'LoadPlugin'.  It will ask you for a DLL to load, and looks in
the directory "Plugins" underneath the PluginTest\bin\Debug directory.

The plugin loader will create an AppDomain and a proxy object inside that
domain, and then call the proxy object, which loads the DLL into its own
AppDomain.

When the plugin starts, it will initiate a worker process in the background
and begin calling the functions that the host process provides.  I've
hardcoded the plugin so that on the (n % 10 == 9) interation, it will throw
an exception.

You will see that both the AppDomain.UnhandledException and the
Appliation.ThreadException receive notification of the exception, but can
do nothing to stop it from terminating the main program.  The target, of
course, is for the main program to be able to say "OK Plugin X had an
exception so I'm going to unload it's AppDomain and continue on with the
rest of my work".

Let me also say (or repeat) that I understand that I could run a process on
the host that calls functions on the plugin, wrapped in a try/catch and
that would probably work.  But I would like my plugins to be in charge of
their own destiny, and not have to rely on some kind of polling from the
hosting application.

-mdb
Author
19 Mar 2006 4:30 AM
Naveen
Hi,
          This is a change in .NET 2.0. Here is a clear write up about
the same.
http://msdn.microsoft.com/netframework/programming/breakingchanges/runtime/clr.aspx

This is a breaking change. It is supposed to be done in v1.1 itself.

But there is a workaround create an App.Config and include this entry

<runtime>
        <legacyUnhandledExceptionPolicy enabled="true" />
    </runtime>

My suggestion would be is to not to use this and try and fix the
problem.
Author
19 Mar 2006 4:59 AM
Michael Bray
Show quote
"Naveen" <naveensrinivasan.nav***@gmail.com> wrote in
news:1142742658.958186.18690@e56g2000cwe.googlegroups.com:

>
> Hi,
>           This is a change in .NET 2.0. Here is a clear write up about
> the same.
> http://msdn.microsoft.com/netframework/programming/breakingchanges/runt
> ime/clr.aspx
>
> This is a breaking change. It is supposed to be done in v1.1 itself.
>
> But there is a workaround create an App.Config and include this entry
>
> <runtime>
>           <legacyUnhandledExceptionPolicy enabled="true" />
>      </runtime>
>
> My suggestion would be is to not to use this and try and fix the
> problem.


Wow...   ok that makes sense as to why I'm seeing this behavior.  I can
handle this if I can somehow prevent code in my AppDomain from creating
threads.  I've been looking at the CAS SecurityPermission's ControlThread
but it doesn't seem to do what I want.  Any suggestions?

-mdb
Author
19 Mar 2006 5:04 PM
Naveen
I dont know how preventing of thread creation would avoid this. But
ControlThread would not stop from creating a thread. It can prevent a
thread from being suspended.
Author
19 Mar 2006 7:44 PM
Michael Bray
"Naveen" <naveensrinivasan.nav***@gmail.com> wrote in
news:1142787856.719864.182010@i39g2000cwa.googlegroups.com:

> I dont know how preventing of thread creation would avoid this. But
> ControlThread would not stop from creating a thread. It can prevent a
> thread from being suspended.
>
>

Its not that it would prevent the problem per se, but if I can prevent the
plugin from creating threads, then I can pretty much guarantee that I can
catch an exception, because I can run the plugin inside a try/catch block. 
As it stands now, the plugin can create threads, and I cannot catch
exceptions that might occur in that thread, and that's what causes the
problem.

-mdb
Author
19 Mar 2006 7:51 PM
Naveen
Ok. What if the plugin uses the ThreadPool? How are you planning to
handle that? Another option is to use HostProtectionAttribute. But to
use this application has to hosted with the HostProtection truned on
(similar to SQL Server 2005).
Author
19 Mar 2006 8:11 PM
Naveen
Hi,
        Here is a sample as to how to use HostProtection to prevent
creation of threads.

http://blogs.msdn.com/shawnfa/archive/2005/10/13/480210.aspx

Naveen
Author
20 Mar 2006 3:58 AM
Michael Bray
"Naveen" <naveensrinivasan.nav***@gmail.com> wrote in
news:1142799063.997411.282140@e56g2000cwe.googlegroups.com:

> http://blogs.msdn.com/shawnfa/archive/2005/10/13/480210.aspx

Thanks!  To answer your previous question, I figured creation of a
ThreadPool thread would be restricted in the same way that creation of a
normal thread would be.

-mdb
Author
20 Mar 2006 4:15 AM
Michael Bray
"Naveen" <naveensrinivasan.nav***@gmail.com> wrote in
news:1142799063.997411.282140@e56g2000cwe.googlegroups.com:

>       Here is a sample as to how to use HostProtection to prevent
> creation of threads.
>
>

Naveen,

Thanks for that link, but unfortunately, I don't think I can use it.  It
seems that the method he describes would affect my host application as well
as the plugins.  This is not the behavior I'm looking for.  I only want to
prevent creation of new threads from the plugins (which I load into a new
AppDomain).  I still need to be able to create threads in the host
application.  Am I correct in this analysis?

-mdb
Author
20 Mar 2006 4:20 AM
Michael Bray
Michael Bray <mbray@makeDIntoDot_ctiusaDcom> wrote in
news:Xns978BEC9BB53B3mbrayctiusacom@207.46.248.16:

> Thanks for that link, but unfortunately, I don't think I can use it.
> It seems that the method he describes would affect my host application
> as well as the plugins.  This is not the behavior I'm looking for.  I
> only want to prevent creation of new threads from the plugins (which I
> load into a new AppDomain).  I still need to be able to create threads
> in the host application.  Am I correct in this analysis?

Here's another idea...   If I can't prevent code that I specify from
creating new threads, is there anything that I can use to determine if code 
makes calls to certain functions, such as Thread.Start or
ThreadPool.QueueUserWorkItem?  If so, then I could simply decide simply to
disallow loading that particular plugin...

-mdb
Author
20 Mar 2006 8:14 PM
Naveen
Hi,
        This can be configured for the plugins alone. By this way the
host application would be able to create threads and manipulate with
them where as the plugins cannot do that. This is the whole idea of
Hosting Interfaces. So this is how when an application with Sql Server
crashes it wont crash the SQL Server. I hope i answered youre question.

Naveen
Author
21 Mar 2006 5:31 AM
Michael Bray
"Naveen" <naveensrinivasan.nav***@gmail.com> wrote in
news:1142885669.266028.163500@u72g2000cwu.googlegroups.com:

>         This can be configured for the plugins alone. By this way the
> host application would be able to create threads and manipulate with
> them where as the plugins cannot do that. This is the whole idea of
> Hosting Interfaces. So this is how when an application with Sql Server
> crashes it wont crash the SQL Server. I hope i answered youre question.

OK So I have this working now - quite nicely actually.  I used the ADMHost
sample and worked it out so that the host application can create threads on
the plugin's behalf, catching any exceptions that occur, but the plugins
can't create threads directly.  This is EXACTLY what I was hoping for.

Now I only have one problem...  The way that my application gets started is
that the ADMHost starts up, and then calls ExecuteAssembly on my EXE file. 
This would be fine, except that ADMHost runs in a text command window.  So
currently, in order to gain the benefit of these controlled AppDomains, I
have this DOS window floating on my desktop.

What can I do to prevent this window from appearing?  Anyone have any
suggestions?

-mdb
Author
20 Mar 2006 6:10 PM
42
In article <Xns9789E05FC9236mbrayctiusacom@207.46.248.16>,
mbray@makeDIntoDot_ctiusaDcom says...
Show quote
> I'm writing a library to support provide plugin capability to my
> applications.  It does this by loading DLL's into a new AppDomain for each
> plugin that is loaded.  Now obviously when I write a plugin, I can make
> sure that my plugins don't throw any exceptions.  But I certainly can't
> guarantee that other people writing plugins won't throw an exception.  The
> problem is that if one of these other plugins throws an exception, it
> brings down the entire application.
>
> Is there anything I can do to prevent Exceptions in other AppDomains from
> bringing down the entire app, when I don't own the code that is running in
> that AppDomain?  I thought I would be able to use
> AppDomain.UnhandledException, but as is pointed out in the link below, this
> is only a "notification" not a "handler".
>
> UnhandledException is not a handler: (watch the wrap)
> http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx?
> feedbackId=FDBK21092

Couldn't you just wrap any calls to functions in the plugin interface in
try/catch blocks?

For example you could write a pluginhost class that implements the
plugin interface, and contains an actual plugin as a private member. All
the plugin interface methods would be just be dispatched to the
contained plugin but wrapped in try/catch constructs.

When you load a plugin you put it inside a pluginhost and interact with
that.
Author
20 Mar 2006 8:25 PM
Michael Bray
42 <nospam@nospam.com> wrote in
news:MPG.1e88901064e36eed989f2d@shawnews.vf.shawcable.net:

> Couldn't you just wrap any calls to functions in the plugin interface
> in try/catch blocks?
>
> For example you could write a pluginhost class that implements the
> plugin interface, and contains an actual plugin as a private member.
> All the plugin interface methods would be just be dispatched to the
> contained plugin but wrapped in try/catch constructs.
>

If my host application was calling the plugin functions, then yes, I
could do what you are suggesting.  The problem arises, however, because
I am allowing the plugins to call functions on the host.

So, for example, when I initialize the plugin, I pass it a reference to
the host with functions such as 'SetHostTitle'.  So it is the plugin
that is making the calls, not the host.  If the plugin only runs on one
thread, then this isn't a problem, because I can wrap the function that
I call on the plugin in a try/catch.  But if the plugin creates a new
thread (to do background work) and that thread makes calls to the host,
then I have no way to control that, and any exceptions thrown in that
background thread will terminate the host application.

That's why I'm currently looking for ways to prevent the plugin from
creating new threads.  (I would provide a function on the host to create
a thread and run a delegate function that the plugin specifies if the
plugin wants to run something in the background, because again I could
run it in a try/catch.)

I've looked at Code Access Protection but I don't think that will work
because the attribute that allows 'Code Execution' (which I obviously
need) also allows thread creation.  There is a 'Control Thread' but it
apparently only controls whether I can perform a Suspend on another
thread, and doesn't prevent thread creation.

I've also looked at Host Protection Attributes, but I don't think that
will work because (from what I can see) it has to be done in the CLR
loader in native code and affects the entire process, which isn't what I
want - I only want to restrict thread creation in specific AppDomains.

My current 'best option' is to decompile the plugin assembly with ILDASM
before I load it and look for references to Thread.Start or
ThreadPool.QueueUserWorkItem.  It's not my preferred way to do it since
there are easy ways around that, such as referencing a secondary dll
that creates the thread for you.

This now feels like an area that the .NET 2.0 CLR developers forgot
about.  It certainly makes sense that Exceptions in threads should NOT
be dropped silently, as I think they were in .NET 1.1, but we as the
programmers should have a way to intercept those exceptions to try to do
something about it.

-mdb
Author
20 Mar 2006 11:55 PM
42
In article <Xns978C9CE7740DAmbrayctiusacom@207.46.248.16>,
mbray@makeDIntoDot_ctiusaDcom says...
Show quote
> 42 <nospam@nospam.com> wrote in
> news:MPG.1e88901064e36eed989f2d@shawnews.vf.shawcable.net:
>
> > Couldn't you just wrap any calls to functions in the plugin interface
> > in try/catch blocks?
> >
> > For example you could write a pluginhost class that implements the
> > plugin interface, and contains an actual plugin as a private member.
> > All the plugin interface methods would be just be dispatched to the
> > contained plugin but wrapped in try/catch constructs.
> >
>
> If my host application was calling the plugin functions, then yes, I
> could do what you are suggesting.  The problem arises, however, because
> I am allowing the plugins to call functions on the host.
>
> So, for example, when I initialize the plugin, I pass it a reference to
> the host with functions such as 'SetHostTitle'.  So it is the plugin
> that is making the calls, not the host.  If the plugin only runs on one
> thread, then this isn't a problem, because I can wrap the function that
> I call on the plugin in a try/catch.  But if the plugin creates a new
> thread (to do background work) and that thread makes calls to the host,
> then I have no way to control that, and any exceptions thrown in that
> background thread will terminate the host application.

Yes. I see now what your issue is.

Show quote
> That's why I'm currently looking for ways to prevent the plugin from
> creating new threads.

> (I would provide a function on the host to create
> a thread and run a delegate function that the plugin specifies if the
> plugin wants to run something in the background, because again I could
> run it in a try/catch.)
>
> I've looked at Code Access Protection but I don't think that will work
> because the attribute that allows 'Code Execution' (which I obviously
> need) also allows thread creation.  There is a 'Control Thread' but it
> apparently only controls whether I can perform a Suspend on another
> thread, and doesn't prevent thread creation.
>
> I've also looked at Host Protection Attributes, but I don't think that
> will work because (from what I can see) it has to be done in the CLR
> loader in native code and affects the entire process, which isn't what I
> want - I only want to restrict thread creation in specific AppDomains.
>
> My current 'best option' is to decompile the plugin assembly with ILDASM
> before I load it and look for references to Thread.Start or
> ThreadPool.QueueUserWorkItem.  It's not my preferred way to do it since
> there are easy ways around that, such as referencing a secondary dll
> that creates the thread for you.

That feels kludgy to me.

> This now feels like an area that the .NET 2.0 CLR developers forgot
> about.  It certainly makes sense that Exceptions in threads should NOT
> be dropped silently, as I think they were in .NET 1.1, but we as the
> programmers should have a way to intercept those exceptions to try to do
> something about it.

Er... they do it seems. The msdn page Naveem posted said:

----

Put a catch block at the top of your non-main thread, threadpool
workitem, or finalizer. (Or else fix the bug that led to the exception.)
Alternatively, in the section of the application's config file, add the
following:

<legacyUnhandledExceptionPolicy enabled="1"/>

----

Naveem only mentioned the legacy route of enabling the old behaviour;
which I agree seems pretty kludgy and dangerous. I think you should be
seeing and at least logging those exceptions, even if you want to
otherwise ignore them.

However; it clearly says you can catch them directly by putting a catch
block "at the top of your non-main thread, threadpool workitem, or
finalizer".

Have you experimented with that? Why is that not suitable for your
needs??

------

As a totally different approach... have you considered running the
"plug-ins" in a completley separate process. Then they can crash and
burn without their child threads throwing unhandled exceptions back into
your host application.

It would add some overhead to the interprocess communication; but it
would give them the separation you are looking for, and the extra
overhead might not cost too much if the plugins aren't too 'chatty'.

-regards,
Dave
Author
21 Mar 2006 12:20 AM
Naveen
Hi,
      The hosting interfaces have
ICLRPolicyManager::SetUnHandledExceptionPolicy which in turn maps to
the legacyUnhandledExceptionPolicy . This is the only way in which you
can ensure that the by an exception thrown by addin dose not kill the
main process. The SQL Server 2005 has implemented the
SetUnHandledExceptionPolicy that prevents the Yukon from crashing if
the addin throws an exception.

And i dont understand as to how this would " pretty kludgy and
dangerous" when Microsoft as implemented with in their Sql Server 2005.

Naveen
Author
21 Mar 2006 1:12 AM
42
In article <1142900454.531707.197***@g10g2000cwb.googlegroups.com>,
naveensrinivasan.nav***@gmail.com says...
> Hi,
>       The hosting interfaces have
> ICLRPolicyManager::SetUnHandledExceptionPolicy which in turn maps to
> the legacyUnhandledExceptionPolicy . This is the only way in which you
> can ensure that the by an exception thrown by addin dose not kill the
> main process.

The document you referenced yourself *seems* to indicate otherwise.

Further, my suggestion of launching it in a separate process would also
isolate it from crashes in the "plugin".

At any rate, enabling "legacy" handling of unhandled exceptions is not
the only way, and doesn't strike me as the best way.

> The SQL Server 2005 has implemented the
> SetUnHandledExceptionPolicy that prevents the Yukon from crashing if
> the addin throws an exception.
>
> And i dont understand as to how this would " pretty kludgy and
> dangerous"

An unhandled exception occurred. The plugin might be malfunctioning,
returning bad data, corrupting data in your host application. I don't
know you could consider it anything BUT dangerous.

I mean I understand why he doesn't want it bring down his whole
application, but just going back to the old way of pretending it didn't
happen doesn't seem very bright either.

> when Microsoft as implemented with in their Sql Server 2005.

What has that got to do with anything? Perhaps it was the easiest way to
get crash prone legacy stuff from becoming totally non-functional.
Microsoft has made a lot security AND stability compromises over the
years in the name of backwards compatibility.
Author
21 Mar 2006 1:45 AM
Naveen
Interprocess communication is very expensive. And if a process has to
be created for an addin then if a host has to load 1000 addins then as
per your advice it would create about 1000 process. In windows
createprocess is one of costliest API that's the reason App Domains
were created. For each process windows creates 10 threads then the
application would end up with 10000 threads.
Creating process for each addin is BAD, BAD idea. Read about the same
here http://blogs.msdn.com/cbrumme/archive/2003/06/01/51466.aspx
Author
21 Mar 2006 4:12 AM
42
In article <1142905520.094110.180***@v46g2000cwv.googlegroups.com>,
naveensrinivasan.nav***@gmail.com says...
> Interprocess communication is very expensive.

True, there is considerable overhead. But whether or not it matters is a
completely separate question. The application *might* need to do little
more than activate the add-in with some inital parameters and forget
about it for 20 minutes.

> And if a process has to
> be created for an addin then if a host has to load 1000 addins then as
> per your advice it would create about 1000 process. In windows
> createprocess is one of costliest API that's the reason App Domains
> were created. For each process windows creates 10 threads then the
> application would end up with 10000 threads.

1000 addins that each need to spawn potentially unstable child threads
to background processing is still a couple thousand threads. And if they
start flaking out and malfunctioning but the exceptions aren't getting
trapped you've still got a royal mess on your hands.

At any rate I'm sure we can come up with a worst case scenario for any
proposal.

> Creating process for each addin is BAD, BAD idea.

That really depends on how many *active* addins there are expected to be
now doesn't it? Obviously in some cases it is a 'bad bad idea', but in
others where the number of addins will be quite small, or where there
may be a pile of addins but only one or two active at a given time, then
it wouldn't be much of an issue at all.
Author
21 Mar 2006 1:54 AM
Michael Bray
42 <nospam@nospam.com> wrote in
news:MPG.1e88e0c42487d883989f2f@shawnews.vf.shawcable.net:
> However; it clearly says you can catch them directly by putting a
> catch block "at the top of your non-main thread, threadpool workitem,
> or finalizer".
>
> Have you experimented with that? Why is that not suitable for your
> needs??


Because it relies on the plugin programmer to do that.  If I was the plugin
programmer, then none of this would be a problem because I would guarantee
to myself that I would wrap everything in a try/catch.  But I can't make
that guarantee about other programmers.

This ties into why I'm trying to prevent the plugin from creating new
threads.  Because if they don't create threads, then I can guarantee that
the plugin host can capture any exceptions.  But if they DO create threads,
then I cannot do this.

> As a totally different approach... have you considered running the
> "plug-ins" in a completley separate process. Then they can crash and
> burn without their child threads throwing unhandled exceptions back
> into your host application.

Yeah I thought about it briefly...   But I'm doing this for my own personal
gratification as anything else, and I want to "do it the right way".  I'm
sure I could probably force things to work if I did it this way, but it
wouldn't feel right.

Incidentally, I've been playing around with the ADMHost sample that Naveen
pointed out, and I feel like I'm close to what I want...  like it's on the
other side of a wall that I just have to figure how to get around.  I'm
still trying to wrap my head around exactly what is going on in ADMHost,
and there are a few things that are confounding me.  Shawn Farkas' ADMHost
modifications feel like the right way to go - I just haven't yet been
successful in integrating it with my plugins library.

Right now, I can create a version of my application that can create
threads, or I can create one that cannot create threads.  I'm trying to
figure out how to let plugin host create threads but not the plugins
themselves.  I'm getting closer.

Here's the ADMHost discussion just for reference:
http://blogs.msdn.com/shawnfa/archive/2005/10/13/480210.aspx

-mdb
Author
21 Mar 2006 6:33 AM
42
In article <Xns978CD4AA8DDB2mbrayctiusacom@207.46.248.16>,
mbray@makeDIntoDot_ctiusaDcom says...
> 42 <nospam@nospam.com> wrote in
> news:MPG.1e88e0c42487d883989f2f@shawnews.vf.shawcable.net:
> > However; it clearly says you can catch them directly by putting a
> > catch block "at the top of your non-main thread, threadpool workitem,
> > or finalizer".
> >
> > Have you experimented with that? Why is that not suitable for your
> > needs??
>
>
> Because it relies on the plugin programmer to do that.

Gotcha, I downloaded your example, and I see what you mean now.

Show quote
>  If I was the plugin
> programmer, then none of this would be a problem because I would guarantee
> to myself that I would wrap everything in a try/catch.  But I can't make
> that guarantee about other programmers.
>
> This ties into why I'm trying to prevent the plugin from creating new
> threads.  Because if they don't create threads, then I can guarantee that
> the plugin host can capture any exceptions.  But if they DO create threads,
> then I cannot do this.
>
> > As a totally different approach... have you considered running the
> > "plug-ins" in a completley separate process. Then they can crash and
> > burn without their child threads throwing unhandled exceptions back
> > into your host application.
>
> Yeah I thought about it briefly...   But I'm doing this for my own personal
> gratification as anything else, and I want to "do it the right way".  I'm
> sure I could probably force things to work if I did it this way, but it
> wouldn't feel right.

Fair enough. Although I'm not sure what the 'right way' would be in this
case, short of being able to trap those exceptions. Anything else seems
a bit of a kludge.

FWIW, I also thought perhaps you could use the unhandled event handler
to record state and your programs last gasp would be to launch itself in
a new process where it could pick up the saved state and continue. But
that's no less a kludge than anything else.

> Incidentally, I've been playing around with the ADMHost sample that Naveen
> pointed out, and I feel like I'm close to what I want...  like it's on the
> other side of a wall that I just have to figure how to get around.  I'm
> still trying to wrap my head around exactly what is going on in ADMHost,
> and there are a few things that are confounding me.  Shawn Farkas' ADMHost
> modifications feel like the right way to go - I just haven't yet been
> successful in integrating it with my plugins library.
>
> Right now, I can create a version of my application that can create
> threads, or I can create one that cannot create threads.  I'm trying to
> figure out how to let plugin host create threads but not the plugins
> themselves.  I'm getting closer.

Yeah, it seems that you are close.

> Here's the ADMHost discussion just for reference:
> http://blogs.msdn.com/shawnfa/archive/2005/10/13/480210.aspx

I'm actually interested in this for a plugin architecture I'm working
with myself -- although in my case I'm not concerned about unhandled
exceptions, but more about malicious plugins. I'd like to restrict what
they can do; not that I think I am likely to make it totally secure, but
I was hoping to make some reasonable attempt at locking them down.

Good luck.
Author
21 Mar 2006 7:10 AM
Michael Bray
42 <nospam@nospam.com> wrote in
news:MPG.1e893e33f947383d989f35@shawnews.vf.shawcable.net:
> Fair enough. Although I'm not sure what the 'right way' would be in
> this case, short of being able to trap those exceptions. Anything else
> seems a bit of a kludge.
> Yeah, it seems that you are close.

I actually have a pretty fair working demo now...   There's only a few
problems I'm currently experiencing:

1.  The ADMHost starts up in a text window - more annoying than a problem
2.  For some reason the plugin has to be in the same directory as the
application if I want to call back to the host to create a thread for the
plugin.

> I'm actually interested in this for a plugin architecture I'm working
> with myself -- although in my case I'm not concerned about unhandled
> exceptions, but more about malicious plugins. I'd like to restrict
> what they can do; not that I think I am likely to make it totally
> secure, but I was hoping to make some reasonable attempt at locking
> them down.

From what I've seen you should be able to utilize CAS pretty effectively
here.  Part of the process of restricting the plugin's ability to create
threads is to grant it Execution permission but outside of a FullTrust
frame.  You could easily add or modify the list of permissions that are
being given to match your local policy.  Of course, there are only so many
things you can restrict, but it should cover most of the typical security
issues.  (Access to file system, registry, etc.)

-mdb

AddThis Social Bookmark Button