MEDIUM: filters: Activate the instances inherited by dynamic backends
The filter instances of the "add backend" CLI command were copied from the
defaults section but never finalized: the parse callbacks of the inherited
instances were not called, the filter-enable, filter-disable and
filter-sequence directives were not applied, and the flat evaluation orders
were not produced. As a result the new backend had no filter analyzer
enabled and no stream filter instance was attached to the streams routed
through it ("show filter instances" already listed the instances as
"enabled, inherited").
Three helpers are added, called by the "add backend" and "del backend" CLI
commands:
- flt_start_new_proxy() finalizes the instances (parse callbacks,
filter-enable/filter-disable, filter-sequence, flattening of the three
evaluation orders) and applies the globally requested filter mode,
mirroring the pre-check stage of the startup. It is called before
proxy_finalize(), while the threads are isolated, so that the filter
analyzers are enabled if the new proxy has filters;
- flt_init_new_proxy() initializes the filters, mirroring the post-check
and per-thread initialization stages. The 'init' callbacks run on the
thread performing the creation, as they run on the main thread during
the startup. The 'init_per_thread' callbacks may initialize thread-local
variables, so they must run on every thread: they are deferred to each
thread with twork items, queued while the threads are still parked by
the thread isolation, and run as their first pending work when they
resume. The backend is not reachable by the switching rules until it is
published with "publish backend", which happens after the items
completed (only "force-be-switch" could select it in-between). Each item
holds a reference on the proxy, so a concurrent "del backend" cannot
destroy it before its per-thread callbacks ran;
- flt_deinit_new_proxy() defers the 'deinit_per_thread' callbacks to every
thread the same way during the deletion, as they may release thread-local
resources (e.g. references in the per-thread Lua states). The proxy is
only destroyed once every thread ran its callbacks, when its last
reference is released.