[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[aspectj-dev] Aspect reentrancy


As part of a study I am doing on cases of aspect reentrancy and how to deal with them, I came across something that seem to be a flaw in the language semantics of AspectJ, at least as implemented by ajc and abc. (I assume abc developers are also reading this list)

By aspect reentrancy, I mean when an aspect matches a join point as part of the execution of an already-matched base program join point (eg. matching a recursive call), of its pointcuts, or of its advice.

For the first case, base-triggered reentrancy, people have learnt to use !cflowbelow(pc()).

For the case of advice-triggered reentrancy, people can use things like !cflow(within(A)) and !cflow(adviceexecution()...).

The strange case is pointcut-triggered reentrancy, that can occur as a consequence of the evaluation of an if pointcut. Consider the following example:

public aspect Tracing {
 before(Point p) : execution(* Point.*(..)) && this(p)
                && if(p.getX() < 0) {

It turns out that this simple aspect always leads to an infinite loop. I could not find a way to specify that the execution of getX caused by the if pointcut be ignored.
!cflow(within(Tracing)) does not work, etc.
As far as I could find, and we have discussed that with Eric Bodden as well in the past days, the only solution for the above Tracing aspect to work is to move the if pointcut into an if condition in the advice. Or are we missing something?

The crux of the problem is that both abc and ajc decide to hide all the join points that are _lexically_ in the if pointcut, but not those that are in the _cflow_ of the if pointcut.
This semantics seems flawed first because it hides join points that are part of the program execution (what if I have an aspect that controls calls to Point getters? it will never be aware that such calls are performed by Tracing); and second because it does not make it possible to avoid pointcut-triggered reentrancy: because the call to getX above is hidden, I cannot discriminate the execution of getX based on the cflow relation to getX...

In any case it seems that the semantics of an aspect should not be changed by moving a test from an if pointcut to the advice.

I'd be happy to know what you think of this problem, in particular if I'm missing a really good reason of why things are the way they are, or that a Tracing aspect as defined above is a bad idea.


-- Éric

PS: I have worked on a detailed analysis of these issues, as well as on a concrete proposal to control aspect reentrancy at a much nicer level of abstraction (IMHO).
An online version of the proposal is available at:
Reactions and comments are very welcome.