[Devel] Feature request: error/debug message extension.

David Robillard d at drobilla.net
Fri Jan 13 16:19:48 PST 2012


On Fri, 2012-01-13 at 07:43 -0600, Gabriel M. Beddingfield wrote:
> On 01/12/2012 04:09 PM, Paul Giblock wrote:
> >> This would let the host do pretty much anything (by putting whatever in
> >> the handle), but also make a trivial implementation extremely simple
> >> (you could literally use pointers to printf and vprintf with a FILE*
> >> handle if you just want to print to stdout anyway).
> >
> > Yes, although the trivial solution is inherently not real-time safe.
> > Good to still have the option for a host to be quick and careless
> > though.
> 
> ...but if there are limits to the size of the string (either imposed by 
> convention, the host, or the plugin), then this can be done RT safe.
> 
> I'm not sure what to think about the hosts being required to supply 
> fprintf-style formatting... I think the plugins themselves should format 
> their own strings and the host just bit-blits them to its internal 
> ringbuffer.  If you want snprintf()... just use snprintf().  I'm pretty 
> sure it's OK for plugins to use std C lib, right?  :-p
> 
> For example:
> 
> #define MY_LOG_FUNC(fmt, ...) {                        \
>      char s[ARBITRARY_LENGTH];                          \
>      snprintf(s, ARBITRARY_LENGTH, fmt, ##__VA_ARGS__); \
>      host_supplied_log_func(s);                         \
> }

Why make plugins do this?  Given the choice, complexity belongs in the
host.

> > Finally, I feel it is a good idea to support the format-string and
> > varg variants. Not only are the plugins relieved from the duty of
> > string-banging while in RT mode, but the host is able to short-circuit
> > the whole thing should the level be under some threshold.
> 
> I usually do short circuiting with a macro like this:
> 
> #define LOG(cond, fmt, ...) { \
>      if(cond) { log_function(fmt, ##__VA_ARGS__); } \
> }
> 
> At runtime, an integer check-and-jump is faster than a function call. 
> This fast short-circuit can only be done by a macro, not a function call.
> 
> So... I suggest that thought be put in to some manner of log-level 
> management.  (Yeah, just the sound of it sounds too complicated, but you 
> know...)  I can envision times when I want:
> 
>      Log output level:  Debug
>      Host logging level: Error
>      Plugin Z's logging level: Debug
>      Plugin Y's logging level: Verbose
>      All other plugins:  Silent
> 
> This requires (at the very least) a callback to the plugin when we want 
> the plugin's log level to change.  Managing the rest is up to the host.

The nice and simple-yet-extensible way of doing this would be to simply
pass a function that takes a level URID and returns a bool, which is
whether or not to log that function.

This has overhead, of course.  I don't see any really sane way of
getting a macro solution like the above, unless plugins cache it at
instantiation time (meaning it couldn't be changed dynamically while
running).

> [1] It's not in the list of async-safe functions, so probably not.  It 
> probably uses malloc() somewhere.  See signal(7).

A wonderful example of exactly why crap like this shouldn't be the
plugin's problem.  If a host can provide an RT safe print function, then
that should be possible.  Every plugin shouldn't have a bunch of
advanced realtime fancy business and custom print messages just to dump
some log messages!

Though, one could make the argument that printing in the audio thread is
simply something you should not be doing anyway, unless you're
debugging, in which case real-time safety doesn't matter...

-dr





More information about the Devel mailing list