| 324 | } |
| 325 | |
| 326 | apr_status_t isapi_lookup(apr_pool_t *p, server_rec *s, request_rec *r, |
| 327 | const char *fpath, isapi_loaded** isa) |
| 328 | { |
| 329 | apr_status_t rv; |
| 330 | const char *key; |
| 331 | |
| 332 | if ((rv = apr_thread_mutex_lock(loaded.lock)) != APR_SUCCESS) { |
| 333 | return rv; |
| 334 | } |
| 335 | |
| 336 | *isa = apr_hash_get(loaded.hash, fpath, APR_HASH_KEY_STRING); |
| 337 | |
| 338 | if (*isa) { |
| 339 | |
| 340 | /* If we find this lock exists, use a set-aside copy of gainlock |
| 341 | * to avoid race conditions on NULLing the in_progress variable |
| 342 | * when the load has completed. Release the global isapi hash |
| 343 | * lock so other requests can proceed, then rdlock for completion |
| 344 | * of loading our desired dll or wrlock if we would like to retry |
| 345 | * loading the dll (because last_load_rv failed and retry is up.) |
| 346 | */ |
| 347 | apr_thread_rwlock_t *gainlock = (*isa)->in_progress; |
| 348 | |
| 349 | /* gainlock is NULLed after the module loads successfully. |
| 350 | * This free-threaded module can be used without any locking. |
| 351 | */ |
| 352 | if (!gainlock) { |
| 353 | rv = (*isa)->last_load_rv; |
| 354 | apr_thread_mutex_unlock(loaded.lock); |
| 355 | return rv; |
| 356 | } |
| 357 | |
| 358 | |
| 359 | if ((*isa)->last_load_rv == APR_SUCCESS) { |
| 360 | apr_thread_mutex_unlock(loaded.lock); |
| 361 | if ((rv = apr_thread_rwlock_rdlock(gainlock)) |
| 362 | != APR_SUCCESS) { |
| 363 | return rv; |
| 364 | } |
| 365 | rv = (*isa)->last_load_rv; |
| 366 | apr_thread_rwlock_unlock(gainlock); |
| 367 | return rv; |
| 368 | } |
| 369 | |
| 370 | if (apr_time_now() > (*isa)->last_load_time + ISAPI_RETRY) { |
| 371 | |
| 372 | /* Remember last_load_time before releasing the global |
| 373 | * hash lock to avoid colliding with another thread |
| 374 | * that hit this exception at the same time as our |
| 375 | * retry attempt, since we unlock the global mutex |
| 376 | * before attempting a write lock for this module. |
| 377 | */ |
| 378 | apr_time_t check_time = (*isa)->last_load_time; |
| 379 | apr_thread_mutex_unlock(loaded.lock); |
| 380 | |
| 381 | if ((rv = apr_thread_rwlock_wrlock(gainlock)) |
| 382 | != APR_SUCCESS) { |
| 383 | return rv; |
no test coverage detected