> So, the intention is that -EINPROGRESS can be returned only on a
> utrace_set_events(task, engine, 0), right?

No, for any call when some bits had been enabled before and there hasn't
been an intervening safe point.  My idea was that it would return 0 only
when it's sure that no disabled callback might be made.  You'd get
-EINPROGRESS any time we aren't 100% positive of that guarantee.

> Actually, I think it would also be useful to just have a
> utrace_clear_events_sync() that encapsulates the above call. I can see
> use for it outside of an asynchronous detach, for cases when one needs
> to just turn tracing events off on a thread. (It is definitely not
> recommended for debugger/probes usage with breakpoints already set in
> user code, but would be useful for someone doing non-invasive syscall
> and process lifetime tracing).

I mentioned utrace_set_events_sync.

> Yes, this does take care of the thread about to die case too.

I've written code to implement most of this.  In working through it, I came
across a couple of other wrinkles I hadn't thought about before.  These
come up in thinking about the possible interactions with callbacks that
return UTRACE_DETACH.

Firstly, you can't call *_sync freely if any of your callbacks ever use
UTRACE_DETACH.  When any callback returns UTRACE_DETACH, immediately the
engine pointer is only kept alive by RCU.  You can't make a blocking call
with rcu_read_lock() held, so you can't be keeping it alive via RCU when
you all *_sync.

You can still use it, just not "freely".  What that means is that you need
some other synchronization with your callbacks.  If your callback safely
updates a data structure saying "already doing the detach", then you can
synchronize with that update and check it before calling utrace_detach_sync.
It takes a little thought to do that without deadlock, but it's doable.

There are already special cases for the report_death callback using
UTRACE_DETACH.  We can see that a death callback might be in progress just
from the task/utrace data structures, without actually looking at the
engine pointer passed in.  So we can relax that rule to allow using
UTRACE_DETACH in report_death without making *_sync unsafe.

The same sort of problems makes me unsure we can use interruptible blocks.

I'll think about this some more.


Thanks,
Roland

Reply via email to