--- modules/database/mod_dbd.c.orig 2006-05-18 10:59:22.000000000 -0700 +++ modules/database/mod_dbd.c 2006-05-18 10:57:10.000000000 -0700 @@ -433,6 +432,7 @@ svr_cfg *svr = ap_get_module_config(s->module_config, &dbd_module); apr_status_t rv = APR_SUCCESS; const char *errmsg; + int tries; if (!svr->persist) { /* Return a once-only connection */ @@ -445,14 +445,33 @@ return NULL; } } - rv = apr_reslist_acquire(svr->dbpool, &rec); - if (rv != APR_SUCCESS) { - ap_log_perror(APLOG_MARK, APLOG_ERR, rv, pool, - "Failed to acquire DBD connection from pool!"); - return NULL; - } - rv = apr_dbd_check_conn(arec->driver, pool, arec->handle); - if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) { + /* PR#39329: implement retries here + * How many times to retry? Well, svr->nkeep is an absolute max + * for the number of connections that could've gone stale while + * the backend remains up. I guess it could go above that in + * some edge case (the database gets restarted?) + * We need 1 try for nkeep = 0 or 1. Hence the dodgy loop logic. + * + * This effect of nkeep needs documenting in TFM. + */ + + tries = svr->nkeep; + do { + rv = apr_reslist_acquire(svr->dbpool, &rec); + if (rv != APR_SUCCESS) { + ap_log_perror(APLOG_MARK, APLOG_ERR, rv, pool, + "Failed to acquire DBD connection from pool!"); + break; + } + rv = apr_dbd_check_conn(arec->driver, pool, arec->handle); + /* mysql wants a second mysql_ping to reopen the connection */ + if (rv == APR_EGENERAL) { + rv = apr_dbd_check_conn(arec->driver, pool, arec->handle); + } + if ((rv == APR_SUCCESS) || (rv == APR_ENOTIMPL)) { + rv = dbd_prepared_init(pool, svr, rec); + break; + } errmsg = apr_dbd_error(arec->driver, arec->handle, rv); if (!errmsg) { errmsg = "(unknown)"; @@ -460,9 +478,9 @@ ap_log_perror(APLOG_MARK, APLOG_ERR, rv, pool, "DBD[%s] Error: %s", svr->name, errmsg ); apr_reslist_invalidate(svr->dbpool, rec); - return NULL; - } - return arec; + } while (--tries > 0); + + return ((rv == APR_SUCCESS) || (rv == APR_ENOTIMPL)) ? arec : NULL; } #else DBD_DECLARE_NONSTD(ap_dbd_t*) ap_dbd_open(apr_pool_t *pool, server_rec *s)