| 621 | } |
| 622 | |
| 623 | static apr_status_t dbd_setup(server_rec *s, dbd_group_t *group) |
| 624 | { |
| 625 | dbd_cfg_t *cfg = group->cfg; |
| 626 | apr_status_t rv; |
| 627 | |
| 628 | /* We create the reslist using a sub-pool of the pool passed to our |
| 629 | * child_init hook. No other threads can be here because we're |
| 630 | * either in the child_init phase or dbd_setup_lock() acquired our mutex. |
| 631 | * No other threads will use this sub-pool after this, except via |
| 632 | * reslist calls, which have an internal mutex. |
| 633 | * |
| 634 | * We need to short-circuit the cleanup registered internally by |
| 635 | * apr_reslist_create(). We do this by registering dbd_destroy() |
| 636 | * as a cleanup afterwards, so that it will run before the reslist's |
| 637 | * internal cleanup. |
| 638 | * |
| 639 | * If we didn't do this, then we could free memory twice when the pool |
| 640 | * was destroyed. When apr_pool_destroy() runs, it first destroys all |
| 641 | * all the per-connection sub-pools created in dbd_construct(), and |
| 642 | * then it runs the reslist's cleanup. The cleanup calls dbd_destruct() |
| 643 | * on each resource, which would then attempt to destroy the sub-pools |
| 644 | * a second time. |
| 645 | */ |
| 646 | rv = apr_reslist_create(&group->reslist, |
| 647 | cfg->nmin, cfg->nkeep, cfg->nmax, |
| 648 | apr_time_from_sec(cfg->exptime), |
| 649 | dbd_construct, dbd_destruct, group, |
| 650 | group->pool); |
| 651 | if (rv != APR_SUCCESS) { |
| 652 | ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(00633) |
| 653 | "failed to initialise"); |
| 654 | return rv; |
| 655 | } |
| 656 | |
| 657 | apr_pool_cleanup_register(group->pool, group, dbd_destroy, |
| 658 | apr_pool_cleanup_null); |
| 659 | |
| 660 | return APR_SUCCESS; |
| 661 | } |
| 662 | #endif |
| 663 | |
| 664 | static apr_status_t dbd_setup_init(apr_pool_t *pool, server_rec *s) |
no test coverage detected