see http://sources.redhat.com/ml/systemtap/2006-q2/msg00286.html Summary of desired behavior: given probe FOO ? { } probe alias = BAR ?, BAZ ? { } If FOO is not found, then that probe should be discarded. If both BAR and BAZ are not found, there are two cases: probe alias { } // ERROR: probepoint not found probe alias ? { } // ok, probe is discarded Similarly, if a syscall "sys_foobar" isn't found: tapset: probe syscall.foobar = kernel.function("sys_foobar") ? {} user script: probe syscall.foobar {} // error, probepoint not found probe syscall.foobar ? {} // ok, probe is discarded probe syscall.* {} // ok if all non-optional syscall probes were found, // or if all are optional, then at least one was found
what about this kind of tapset, user script should care nothing about whether is it optional or not. tapset: probe syscall.foobar = kernel.function("sys_foobar") ? {} optional probe syscall.foobar1 = kernel.function("sys_foobar1") {} non-optional user script: probe syscall.foobar {} // ok, probe is discarded probe syscall.foobar1 {} // ERROR: probepoint not found probe syscall.* {} // ok if all non-optional syscall probes were found, // or if all are optional, then at least one was found
(In reply to comment #1) > what about this kind of tapset, user script should care nothing about > whether is it optional or not. The user doesn't know whether the lower level tapset has marked a binding as optional or not. Thus, when the user writes a probe on syscall.foobar, they will likely be surprised if this probe was automatically removed. We should avoid surprising results. At a minimum this should be an warning, but I still think it's better to be an error.
If I understand the concern correctly, in this scenario, probe group.f = pp ? { } # in tapset probe group.* { } # in user script and for missing "pp", should this succeed or fail? There is an ambiguity. With the current flavouring of the code, it would fail, since the group.* match would expand to an empty set of derived_probe's. With a little bit of extra work, we can let the tapset author make this pass. Let's provide a new probe point "never", which would be similar to "begin" and "end" but never actually run its handler. (It doesn't even need to show up in the translated C code.) Then, if a tapset author wants to make the alias succeed with a missing pp, even for non-optional users, he can say: probe group.f = pp ? , never { } # in tapset
(In reply to comment #3) > If I understand the concern correctly, in this scenario, > probe group.f = pp ? { } # in tapset > probe group.* { } # in user script > and for missing "pp", should this succeed or fail? There is an ambiguity. > With the current flavouring of the code, it would fail, since the group.* > match would expand to an empty set of derived_probe's. I think failure is correct here. With missing "pp", "group.*" should fail, yet "group.* ?" would be ok. If there were another alias, "probe group.g = qq ? {}", then "group.*" will succeed iff at least one of "pp" and "qq" are found. > With a little bit of extra work, we can let the tapset author make this pass. > Let's provide a new probe point "never", which would be similar to "begin" > and "end" but never actually run its handler. (It doesn't even need to show > up in the translated C code.) Then, if a tapset author wants to make the > alias succeed with a missing pp, even for non-optional users, he can say: > probe group.f = pp ? , never { } # in tapset I think this is a good workaround if a tapset author really wants to write a probe that could possibly do nothing. While I personally think this should be discouraged, for the reasons I gave in comment #2, it may be good to allow this possibility to cover all use cases.
patch committed
Patch confirmed. I made changes to the process tapset to take advantage of this, and it appears to work very well. This is a powerful capability for tapset authors -- thank you!
Sorry to reopen this -- I found a case that doesn't work, but probably should: probe alias = kernel.function("foobar") { } probe alias ? { } semantic error: no match for probe point while: resolving probe point kernel.function("foobar") The use of 'alias' is marked optional, so this shouldn't be an error.
let's try that one again :-) (BTW, the "process.signal_handle" alias doesn't expand at all on my FC5 machine.)
(In reply to comment #8) > let's try that one again :-) Better -- you indeed pass the test I gave before. How about multiple levels of indirection? probe x = kernel.function("foobar") {} probe y = x {} probe y ? {} semantic error: no match for probe point while: resolving probe point kernel.function("foobar") Pass 2: analysis failed. Try again with more '-v' (verbose) options. :( > (BTW, the "process.signal_handle" alias doesn't expand at all on my FC5 machine.) Strange - it works for me. On i686 RHEL4 it expands to the function version, and on x86_64 FC5 it expands to the inline version. The function being probed (handle_signal) is not marked as inline, so apparently the compiler is taking liberties. Either way, that function should definitely exist! I would suspect this is a compiler/elfutils issue, so we may need a new bug opened.
> How about multiple levels of indirection? I'm unsure about to what extent it makes sense to push "?" all the way down. If it's obviously sensible, it can be implemented e.g. by having the alias_expansion_builder::build routine pass the incoming location->optional flag to the alias_derived_probe->locations[]. Multiple levels of implicit optionality make me a bit uneasy. In your example, the author of the middle alias ("probe y = x {}") could be interpreted as asserting x's existence.
> How about multiple levels of indirection? The new code passes down "?" from outer to inner levels of indirection.
(In reply to comment #10) > the author of the middle alias ("probe y = x {}") could be interpreted as > asserting x's existence. Except that if 'y' is never instantiated, there's no error. It's not until there's a use of 'y' that an error is generated, and if that use is marked optional, then why should it be an error? (In reply to comment #11) > The new code passes down "?" from outer to inner levels of indirection. Verified. I have another weird case, but I'm not sure of the right answer here. probe x = kernel.function("sys_open"), kernel.function("foobar") {} probe x {/*1*/} probe x ? {/*2*/} #1 generates an error, and rightly so. #2 results in a probe on "sys_open" only, ignoring the missing "foobar". Is this what we want? Or should 'x' be treated as an entire entity, such that if not all required components of 'x' are found, it is omitted completely. That is, #2 would be completely removed if 'x' cannot be expanded correctly -- all or nothing. It feels weird to me either way, so I'd like to hear another opinion.
It seems to me like your two examples in comment #12 somewhat contradict each other. I'd like to retreat from complexity and try the current simple-to-explain behavior ("? is pushed down all the way through wildcard / alias expansion") for a while.
I'll grant that I may have been overthinking it -- in the quest for completeness, it's easy to lose sight. I always figure it's better to document any & all concerns, because it's easy to forget them later. What you've implemented now looks good.