exception not propagating correctly

R

RRIMSDN

Note this is a repost of an earlier thread (from Dec 2004) under my new,
no spam MSDN alias since Microsoft changed the no spam alias rules and
didn't tell anyone (you have to re-register a no spam alias to get a
special domain extension in order for Microsoft to respond to posts).

----------

This refers to KB article #836674
(http://support.microsoft.com/?kbid=836674). I encountered the bug
described in that article, but neither of the workarounds are entirely
satisfactory.

The first workaround, creating the App.config file, only seems to work
when making a debug build.

The second workaround solves the problem, but the process of re-throwing
the exception causes the stack trace contained in the exception to be
reset. The result is that when the exception is finally caught, the
stack trace shows the call stack at the point where the
ThreadExceptionEventHandler re-threw it, instead of where the exception
was originally thrown.

So, is there any way around this? Can I somehow throw the exception
without having its stack trace altered? I don't want to change the code
that eventually catches the exception to deal with this, I would like to
simply get the behavior as it should be if this bug didn't exist at all.
 
J

Jeffrey Tan[MSFT]

Hi RRIMSDN,

Thanks for your posting!

I have viewed that KB and did some test for this.

Yes, for the first workaround, it really does not work for project release
build.

But for the second workaround, does the following way makes sense to you:

Application.ThreadException+=new
System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

private static void Application_ThreadException(object sender,
System.Threading.ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.StackTrace);
}

That is do not throw a new exception in ThreadException method, just show
out the stacktrace in ThreadException. This will result in the same
StackTrace. Anyway, if you still have any concern, please feel free to tell
me. Thanks
==================================================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
R

RRIMSDN

We know how to get the stack trace; what we really want to know is how
we can re-throw the exception while preserving that stack trace. We
want the original stack trace to be part of the exception thrown from
this work around. We know we can put the original exception as an inner
exception to preserve it, but we don't want to do that because then we
end up changing the type of exception thrown, and we want to preserve
the original exception type. Basically all we want to know is if there
is a way to throw the exception while preserving the stack trace. Is
there any way to do that?

thanks
 
C

Chris

If you throw a *new* application exception, can you set the new
exceptions InnerException property to the current exception?

You should then be able to get the stack trace information from the
InnerException.

Just a thought,

Chris
 
J

Jeffrey Tan[MSFT]

Hi RRIMSDN,

Yes, I see your concern. Based on my experience, this can not be done. I
think the Chris's suggestion of storing the original exception as the
innerexception is a good workaround for this issue, althrough I see that
you did not like this workaround.

May I ask why you MUST re-throw the exception in ThreadException event
handler? I suspect you only want to intercept all the exceptions in the
application and display its details information, so I think ThreadException
event handler which acts as a global handler should meet your need. If I
misunderstand you, please feel free to tell me, thanks.
==================================
Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
R

RRIMSDN

We must rethrow because we don't want duplicate code for handling this
work around case from our other cases, and we don't want to show the
stack trace, we want to log it and perhaps do other things further up
the call stack, and not necessarily right at this work around's spot.
The managed part of the app is controlled/created by unmanaged code, so
we need to translate the exception information into something that can
be returned to the unmanaged app. The unmanaged app is the one that has
to deal with the exception.

At this point, we will use the workaround of wrapping it in an inner
exception, even though that means we have to change the code that
catches the exception.

Is this problem expected (or already) fixed in the next version, 2005,
of Visual Studio?

thanks
 
J

Jeffrey Tan[MSFT]

Hi RRIMSDN,

Thanks very much for your feedback!

Yes, I see your concern, your have placed an exception handler in
somewhere, so you wanted forward the unhandled exception from the
ThreadException handler to this exception handler. Then there is not much
code that you have to modify.

But currently, I did not think of a perfect solution for this issue, and
some extra modification for code is necessary.

I am not sure if VS.net 2005 will finally fix this issue, you may download
the lastest beta version of VS.net2005 and did some test on it.

Also, I will forward your concern for this issue to the owner of that KB
and our product team.

Hope this helps.

Thank you for your patience and cooperation. If you have any questions or
concerns, please feel free to post it in the group. I am standing by to be
of assistance.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
G

Guest

I need to be able to preserve an exception Stack Trace for a different
reason. I am writing asynchronous objects. Like a socket object.

Here is some example code:

private void cmdCauseAsynchronousException_Click(object sender,
System.EventArgs e)
{

log.Write("Calling Begin...");

BeginTask(new AsyncCallback(TaskCompleteCallbackProcessor), null);

log.Write("Begin called");

}

private void TaskCompleteCallbackProcessor(IAsyncResult asyncResult)
{

log.Write("Callback calling end");
try
{
EndTask(asyncResult);
log.Write("End called");
}
catch(Exception e)
{
string ex = "";
Exception current = e;
while( current != null )
{
ex = "Exception:\r\n" + current.Message + "\r\n" + current.StackTrace +
"\r\n" + ex;
current = current.InnerException;
}

log.Write("Exception while calling end" + ex);
}

}


private IAsyncResult BeginTask(AsyncCallback Callback, object State)
{
CallerAsyncResult callerAsyncResult = new CallerAsyncResult(Callback, State);

ThreadPool.QueueUserWorkItem(new WaitCallback(PerformAsyncTask),
callerAsyncResult);

return callerAsyncResult;

}

private void PerformAsyncTask(object State)
{

CallerAsyncResult callerAsyncResult = (CallerAsyncResult)State;

try
{ // Task try block
// Simulate task
Thread.Sleep(TimeSpan.FromMilliseconds(500.00));
// Simulate task throwing exception
throw new Exception("Junk that is garbage");
}
catch(Exception e)
{
callerAsyncResult.Complete(e);
}

callerAsyncResult.Complete(null);

}

private void EndTask(IAsyncResult asyncResult)
{

CallerAsyncResult callerAsyncResult = (CallerAsyncResult)asyncResult;

callerAsyncResult.WaitForCompletion();

if(callerAsyncResult.exception != null)
throw new Exception(callerAsyncResult.exception.Message,
callerAsyncResult.exception);

}



public class CallerAsyncResult : IAsyncResult
{

protected int isCompleted = 0;
protected int invokedCallback = 0;
internal protected bool completedSynchronously = true;
protected ManualResetEvent asyncOperationCompletedEvent = null;
protected object asyncState = null;
protected AsyncCallback callback = null;
internal protected Exception exception = null;
internal protected object operationResult = null;

public CallerAsyncResult(AsyncCallback CallersCallback, object State)
{
asyncState = State;
callback = CallersCallback;
asyncOperationCompletedEvent = new ManualResetEvent(false);
}

public virtual void ReInit(AsyncCallback CallersCallback, object State)
{
completedSynchronously = true;
asyncOperationCompletedEvent.Reset();
asyncState = State;
callback = CallersCallback;
isCompleted = 0;
invokedCallback = 0;
exception = null;
}


public virtual void Complete(Exception e)
{
this.exception = e;
Complete();
}

public virtual void Complete(object OperationResult)
{
operationResult = OperationResult;
Complete();
}

private void Complete()
{
if(Interlocked.Increment(ref isCompleted) == 1)
{
asyncOperationCompletedEvent.Set();
}
PerformCallback();
}

private void PerformCallback()
{
if(Interlocked.Increment(ref invokedCallback)==1)
{
if(callback != null)
{
callback(this);
}
}
}

public virtual void WaitForCompletion()
{
if(isCompleted == 0)
{
asyncOperationCompletedEvent.WaitOne();
}
}

public virtual void ClearObjectReferencesForReuse()
{
asyncState = null;
callback = null;
exception = null;
}

public object AsyncState
{
get
{
return asyncState;
}
}

public WaitHandle AsyncWaitHandle
{
get
{
return asyncOperationCompletedEvent;
}
}

public bool CompletedSynchronously
{
get
{
return completedSynchronously;
}
}

public bool IsCompleted
{
get
{
return (isCompleted != 0);
}
}
}


Now here is my problem.

As you can see where I implemented the work-around and set the original
exception to be the InnerException of a new Exception.
"throw new Exception(callerAsyncResult.exception.Message,
callerAsyncResult.exception);"

I'd much rather be able to do this:
"thow callerAsyncResult.exception;"
and have the exception append to its existing stack trace rather than throw
out the stack trace that it already has.

Here is why, suppose I have several nested layers of asynchronous streams
with a socket deep underneath. I wish to make asynchronous calls to these
streams and I wish to selectively catch the socket exceptions from the top to
detect a network faliure. If I create a new exception then the exception
type is not preserved making this impossible.
 
G

Guest

I suppose I could implement the Exception.GetBaseException() method to work
around this problem. I will need to use Exception.GetBaseException() for all
my high level try catch blocks.

Say I have the following high level code:

NetworkStream nsBaseStream = new NetworkStream(connectedSocket);

MyCustomStream ms = new MyCustomStream(nsBaseStream);

IAsyncResult res = ms.BeginRead(null, null);

try
{
ms.EndRead(res);
}
catch(SecurityException se)
{
// handle security exception, say code access security denies a call to
something that MyStream uses
}
catch(SocketException se)
{
// If the exception type was not preserved I would not catch this
// Since I can't rethrow and save an InnerException simultaneously then
// I must create a new exception, but if I create a new exception then
// this catch block will never execute because the exception type will
probably change
// If I re-throw the exception then I will lose the original stack trace
}


Versus this code which makes use of GetBaseException


NetworkStream nsBaseStream = new NetworkStream(connectedSocket);

MyCustomStream ms = new MyCustomStream(nsBaseStream);

IAsyncResult res = ms.BeginRead(null, null);


try
{
ms.EndRead(res);
}
catch(SecurityException se)
{
// handle security exception, say code access security denies a call to
something that MyStream uses
}
catch(Exception e)
{
Exception baseEx = e.GetBaseException();
if(typeof(SocketException ) == baseEx.GetType())
{
// handle socket exception that should have bubbled up from low
level code if the socket connection to the remote host fails
}
else
{
// here is the problem again, I have solved one problem to
create another
// If I re-throw then I'll lose the stack trace, or perhaps
just throw will preserve it?
throw; // ??
}
}


If this last code example works it is a pretty inelegant work-around.
Especially if I want an easy to use code library. Imagine trying to educate
people on how to handle exceptions from your library using the
GetBaseException method.
 
G

Guest

I have solved my problems by creating the following class:

public class AsynchronousException : ApplicationException
{
public AsynchronousException(Exception innerException) :
base(innerException.Message, innerException)
{

}

public override Exception GetBaseException()
{
return base.GetBaseException ();
}

}




I have changed my End Task Event to throw this exception when an
asynchronous exception is thrown.

private void EndTask(IAsyncResult asyncResult)
{

CallerAsyncResult callerAsyncResult = (CallerAsyncResult)asyncResult;

callerAsyncResult.WaitForCompletion();

if(callerAsyncResult.exception != null)
{
throw new AsynchronousException(callerAsyncResult.exception.Message,
callerAsyncResult.exception);
}

}




If an AsychronousException is thrown when I call EndTask then I know that I
must get the base exception to really see what is going on:

log.Write("Callback calling end");
try
{
EndTask(asyncResult);
log.Write("End called");
}
catch(AsynchronousException ae)
{
Exception baseException = ae.GetBaseException();
if(baseException.GetType() == typeof(SocketException))
{
// Handle this type of exception here
}
else
{
// Hande other asynchronous exceptions
}
}

If another Exception is thrown it can be caught by another catch block.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top