diff --git a/lib/app_profiler.rb b/lib/app_profiler.rb index 92383d4..35e48bb 100644 --- a/lib/app_profiler.rb +++ b/lib/app_profiler.rb @@ -127,7 +127,7 @@ def profiler def backend=(new_backend) return if (new_profiler_backend = backend_for(new_backend)) == profiler_backend - if running? + if profiler_backend.locked? raise BackendError, "cannot change backend to #{new_backend} while #{backend} backend is running" end @@ -269,7 +269,7 @@ def profiler_backend end def clear - profiler.stop if running? + profiler.stop if profiler_backend.locked? @profiler = nil @profiler_backend = nil end diff --git a/lib/app_profiler/backend/base_backend.rb b/lib/app_profiler/backend/base_backend.rb index abc886a..bbfe8cc 100644 --- a/lib/app_profiler/backend/base_backend.rb +++ b/lib/app_profiler/backend/base_backend.rb @@ -47,6 +47,10 @@ def run_lock @run_lock ||= Mutex.new end + def locked? + run_lock.locked? + end + def name raise NotImplementedError end diff --git a/test/app_profiler/backend_test.rb b/test/app_profiler/backend_test.rb index 8cd78b5..210094d 100644 --- a/test/app_profiler/backend_test.rb +++ b/test/app_profiler/backend_test.rb @@ -27,6 +27,24 @@ class BackendTest < TestCase AppProfiler.backend = orig_backend end + test ".backend= updates the backend while a foreign StackProf session is active" do + orig_backend = AppProfiler.backend + skip("Vernier not supported") unless AppProfiler.vernier_supported? + AppProfiler.backend = AppProfiler::Backend::StackprofBackend.name + AppProfiler.profiler # force @profiler memoization so AppProfiler.running? actually delegates + + StackProf.start(mode: :wall, interval: 1000) + begin + AppProfiler.backend = AppProfiler::VernierProfile::BACKEND_NAME + assert_equal(AppProfiler::VernierProfile::BACKEND_NAME, AppProfiler.backend) + ensure + StackProf.stop + StackProf.results + end + ensure + AppProfiler.backend = orig_backend + end + test ".backend= accepts a symbol with the backend name" do orig_backend = AppProfiler.backend skip("Vernier not supported") unless AppProfiler.vernier_supported? diff --git a/test/app_profiler/run_test.rb b/test/app_profiler/run_test.rb index 09f42ac..24f9a91 100644 --- a/test/app_profiler/run_test.rb +++ b/test/app_profiler/run_test.rb @@ -59,5 +59,27 @@ class RunTest < TestCase ensure AppProfiler.backend = orig_backend end + + test ".run swaps backend even while a foreign StackProf session is active" do + orig_backend = AppProfiler.backend + skip("Vernier not supported") unless AppProfiler.vernier_supported? + AppProfiler.backend = AppProfiler::Backend::StackprofBackend.name + AppProfiler.profiler # force @profiler memoization so AppProfiler.running? actually delegates + + StackProf.start(mode: :wall, interval: 1000) + begin + profile = AppProfiler.run(backend: AppProfiler::VernierProfile::BACKEND_NAME) do + sleep(0.01) + end + + assert_instance_of(AppProfiler::VernierProfile, profile) + assert_equal(AppProfiler::Backend::StackprofBackend.name, AppProfiler.backend) + ensure + StackProf.stop + StackProf.results + end + ensure + AppProfiler.backend = orig_backend + end end end