Accessing the CALL STACK

Y

Yahoo

I have a programming issue where I need to know the whole history of the
call stack to ensure it was never within a given method (specifically my own
method). I am hooking into the XmlDocument nodechanged event, I need to from
this event call modify a different node in this xmldocument, thus without
somekind of check we will be off in an infinite loop. Currently I am using
the System.Diagnostics classes but feel its not right to use these classes
like this. I would expect a master call stack to be kepted in the threading
class (or even reflections) but i dont see it. Is there a better way?


private bool IsFromUs()

{

StackTrace stackTrace = new StackTrace();

StackFrame stackFrame;

MethodBase stackFrameMethod;

string typeName;

//find the first system.xml method, this always exists

int position=0;

for(int x = position; x<stackTrace.FrameCount; x++)

{

stackFrame = stackTrace.GetFrame(x);

stackFrameMethod = stackFrame.GetMethod();

typeName = stackFrameMethod.ReflectedType.FullName;


if (typeName.StartsWith("System.Xml"))

{

position = x;

break;

}

}

//now determine if we were the cause of this notification

for(int x = position; x<stackTrace.FrameCount; x++)

{

stackFrame = stackTrace.GetFrame(x);

stackFrameMethod = stackFrame.GetMethod();

typeName = stackFrameMethod.ReflectedType.FullName;


if (typeName.StartsWith("RuleEngine"))

return true;

}

return false;

}
 
N

Nicholas Paldino [.NET/C# MVP]

The StackTrace/StackFrame class is the way that you would access call
stack information. There really isn't another way.

However, you shouldn't be doing this. Getting the call stack is
expensive, not to mention the fact that you should implement better logic to
determine if you are re-entering your own function.

Hope this helps.
 
Y

Yahoo

I know its a real performance hit, but thats ok for now. Before this i was
implementing a balking design pattern where I was cheking the status on the
nodechanged but that was causing other problems. Thanks for the quick
response.


Nicholas Paldino said:
The StackTrace/StackFrame class is the way that you would access call
stack information. There really isn't another way.

However, you shouldn't be doing this. Getting the call stack is
expensive, not to mention the fact that you should implement better logic
to determine if you are re-entering your own function.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Yahoo said:
I have a programming issue where I need to know the whole history of the
call stack to ensure it was never within a given method (specifically my
own method). I am hooking into the XmlDocument nodechanged event, I need
to from this event call modify a different node in this xmldocument, thus
without somekind of check we will be off in an infinite loop. Currently I
am using the System.Diagnostics classes but feel its not right to use
these classes like this. I would expect a master call stack to be kepted
in the threading class (or even reflections) but i dont see it. Is there a
better way?


private bool IsFromUs()

{

StackTrace stackTrace = new StackTrace();

StackFrame stackFrame;

MethodBase stackFrameMethod;

string typeName;

//find the first system.xml method, this always exists

int position=0;

for(int x = position; x<stackTrace.FrameCount; x++)

{

stackFrame = stackTrace.GetFrame(x);

stackFrameMethod = stackFrame.GetMethod();

typeName = stackFrameMethod.ReflectedType.FullName;


if (typeName.StartsWith("System.Xml"))

{

position = x;

break;

}

}

//now determine if we were the cause of this notification

for(int x = position; x<stackTrace.FrameCount; x++)

{

stackFrame = stackTrace.GetFrame(x);

stackFrameMethod = stackFrame.GetMethod();

typeName = stackFrameMethod.ReflectedType.FullName;


if (typeName.StartsWith("RuleEngine"))

return true;

}

return false;

}
 
M

Marcus Andrén

I have a programming issue where I need to know the whole history of the
call stack to ensure it was never within a given method (specifically my own
method). I am hooking into the XmlDocument nodechanged event, I need to from
this event call modify a different node in this xmldocument, thus without
somekind of check we will be off in an infinite loop. Currently I am using
the System.Diagnostics classes but feel its not right to use these classes
like this. I would expect a master call stack to be kepted in the threading
class (or even reflections) but i dont see it. Is there a better way?

Wouldn't the following code work:

// Each thread gets its own isMethodActive variable. So the method can
// be called on several threads at once.
[ThreadStatic]
static bool isMethodActive=false;

public void Method()
{
if (isMethodActive)
return; //Method is already called. Exit to avoid infinite loop.
isMethodActive=true;
try
{
/* Do recursive call here */
}
finally
{
isMethodActive=false;
}
}
 
Y

Yahoo

I might be mistaken but i dont thing this would work becuase the
isMethodActive is static, other instances of the object who should be
allowed access would be restricted. it would probably work as an instance
variable with a proxy design pattern where outside calls in the proxy would
set the ismethodactive to true, internal calls that then trigger the
nodechange could then be ignored. I dont think it would be thread safe since
another thread could be denied when it shouldnt be.


Marcus Andrén said:
I have a programming issue where I need to know the whole history of the
call stack to ensure it was never within a given method (specifically my
own
method). I am hooking into the XmlDocument nodechanged event, I need to
from
this event call modify a different node in this xmldocument, thus without
somekind of check we will be off in an infinite loop. Currently I am using
the System.Diagnostics classes but feel its not right to use these classes
like this. I would expect a master call stack to be kepted in the
threading
class (or even reflections) but i dont see it. Is there a better way?

Wouldn't the following code work:

// Each thread gets its own isMethodActive variable. So the method can
// be called on several threads at once.
[ThreadStatic]
static bool isMethodActive=false;

public void Method()
{
if (isMethodActive)
return; //Method is already called. Exit to avoid infinite loop.
isMethodActive=true;
try
{
/* Do recursive call here */
}
finally
{
isMethodActive=false;
}
}
 
M

Marcus Andrén

I might be mistaken but i dont thing this would work becuase the
isMethodActive is static, other instances of the object who should be
allowed access would be restricted. it would probably work as an instance
variable with a proxy design pattern where outside calls in the proxy would
set the ismethodactive to true, internal calls that then trigger the
nodechange could then be ignored. I dont think it would be thread safe since
another thread could be denied when it shouldnt be.

True. If you want to allow the method to be called once for each
instance, just remove the static declaration.

If you need it to be threadsafe, replace the static boolean with a
static Hashtable and add/remove 'this'. It is still much better than
trying to look in the stacktrace.
 
J

Jon Skeet [C# MVP]

Yahoo said:
I might be mistaken but i dont thing this would work becuase the
isMethodActive is static, other instances of the object who should be
allowed access would be restricted.

You missed the fact that it's marked with the ThreadStatic attribute.
That means there's basically one variable per thread, which is exactly
what you want.
 
G

Guest

in addition to the ThreadStatic idea, you can also dettach from the event on
entering the handler, and re-attach before exit.
 
Y

Yahoo

Tried this and had problems. Issue is the client could...

client->myobjmethod1->myobjectmethod2

or they could

client->myobjectmethod2

So in the second method you wouldnt want to add them back in if myobjmethod1
called it cuz that would mess it up for the rest of mymethod1.
 
Y

Yahoo

I didnt miss the threadstatic att, the problem can be caused when...

client->myobj1

now the ismethodactive for this thread is true. next...

client-> xmldocument->myobj1->myobj2

they should have access to myobj2 but since its of the same type and has a
static (per thread) they will be denied. Heres the problem... its ok if my
objects calls themself (they in the know), but i when myobj1 updates the
xmldocument (or even does the selectsinglenode causing a createnavigator
object to be created) the nodechange event is fired and we end up in with a
stack overflow exception

client->xmldocument->myobj1->xmldocument->myobj1->xmldocuemnt->.....->StackOverflow
Exception

I am thinking that I have a big fundamental design issue?
 
J

Jon Skeet [C# MVP]

Yahoo said:
I didnt miss the threadstatic att

I think I misunderstood your comment then.
the problem can be caused when...

client->myobj1

now the ismethodactive for this thread is true. next...

client-> xmldocument->myobj1->myobj2

they should have access to myobj2 but since its of the same type and has a
static (per thread) they will be denied. Heres the problem... its ok if my
objects calls themself (they in the know), but i when myobj1 updates the
xmldocument (or even does the selectsinglenode causing a createnavigator
object to be created) the nodechange event is fired and we end up in with a
stack overflow exception

client->xmldocument->myobj1->xmldocument->myobj1->xmldocuemnt->.....->StackOverflow
Exception

I am thinking that I have a big fundamental design issue?

Well, the ThreadStatic hashtable idea is probably the best one.
(Alternatively, each object could have a hashtable of threads which
were currently "inside" the method.)
 
Top