X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2Ffibers%2Ftest%2FFibersTest.cpp;h=b3d32303c91441a475e2256ea4b152a7f49e995b;hp=d1b60cee6b13c69f9236dce3f4a20a9e49a6f064;hb=de821c225980359651a07b670174ae90d4f655c8;hpb=eac2f407712046f9a3b91c244301467d31ec3819 diff --git a/folly/fibers/test/FibersTest.cpp b/folly/fibers/test/FibersTest.cpp index d1b60cee..b3d32303 100644 --- a/folly/fibers/test/FibersTest.cpp +++ b/folly/fibers/test/FibersTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2016 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -291,7 +292,7 @@ TEST(FiberManager, addTasksNoncopyable) { if (!taskAdded) { manager.addTask([&]() { std::vector()>> funcs; - for (size_t i = 0; i < 3; ++i) { + for (int i = 0; i < 3; ++i) { funcs.push_back([i, &pendingFibers]() { await([&pendingFibers](Promise promise) { pendingFibers.push_back(std::move(promise)); @@ -1863,7 +1864,7 @@ void dispatchJobs( if (dispatchProblem == DispatchProblem::DuplicateDispatch) { if (i == problemIndex) { - EXPECT_THROW(job.token.dispatch(job.input), std::logic_error); + EXPECT_THROW(job.token.dispatch(job.input), ABDUsageException); } } } catch (...) { @@ -1963,12 +1964,12 @@ TEST(FiberManager, ABD_DispatcherDestroyedBeforeCallingCommit) { dispatchJobs(executor, jobs, results); throw std::runtime_error( "Unexpected exception in user code before commit called"); - atomicBatchDispatcher.commit(); + // atomicBatchDispatcher.commit(); } catch (...) { /* User code handles the exception and does not exit process */ } evb.loop(); - validateResults(results, COUNT); + validateResults(results, COUNT); } TEST(FiberManager, ABD_PreprocessingFailureTest) { @@ -1984,7 +1985,7 @@ TEST(FiberManager, ABD_PreprocessingFailureTest) { dispatchJobs(executor, jobs, results, DispatchProblem::PreprocessThrows, 8); atomicBatchDispatcher.commit(); evb.loop(); - validateResults(results, COUNT - 1); + validateResults(results, COUNT - 1); } TEST(FiberManager, ABD_MultipleDispatchOnSameTokenErrorTest) { @@ -2013,12 +2014,12 @@ TEST(FiberManager, ABD_GetTokenCalledAfterCommitTest) { createAtomicBatchDispatcher(std::move(dispatchFunc)); createJobs(atomicBatchDispatcher, jobs, COUNT); atomicBatchDispatcher.commit(); - EXPECT_THROW(atomicBatchDispatcher.getToken(), std::logic_error); + EXPECT_THROW(atomicBatchDispatcher.getToken(), ABDUsageException); dispatchJobs(executor, jobs, results); - EXPECT_THROW(atomicBatchDispatcher.getToken(), std::logic_error); + EXPECT_THROW(atomicBatchDispatcher.getToken(), ABDUsageException); evb.loop(); validateResults(results, COUNT); - EXPECT_THROW(atomicBatchDispatcher.getToken(), std::logic_error); + EXPECT_THROW(atomicBatchDispatcher.getToken(), ABDUsageException); } TEST(FiberManager, ABD_UserProvidedBatchDispatchThrowsTest) { @@ -2041,37 +2042,97 @@ TEST(FiberManager, ABD_UserProvidedBatchDispatchThrowsTest) { } TEST(FiberManager, VirtualEventBase) { - folly::ScopedEventBaseThread thread; - - auto evb1 = - folly::make_unique(*thread.getEventBase()); - auto evb2 = - folly::make_unique(*thread.getEventBase()); - bool done1{false}; bool done2{false}; + { + folly::ScopedEventBaseThread thread; - getFiberManager(*evb1).addTaskRemote([&] { - Baton baton; - baton.timed_wait(std::chrono::milliseconds{100}); + auto evb1 = + folly::make_unique(*thread.getEventBase()); + auto& evb2 = thread.getEventBase()->getVirtualEventBase(); - done1 = true; - }); + getFiberManager(*evb1).addTaskRemote([&] { + Baton baton; + baton.timed_wait(std::chrono::milliseconds{100}); - getFiberManager(*evb2).addTaskRemote([&] { - Baton baton; - baton.timed_wait(std::chrono::milliseconds{200}); + done1 = true; + }); - done2 = true; - }); + getFiberManager(evb2).addTaskRemote([&] { + Baton baton; + baton.timed_wait(std::chrono::milliseconds{200}); + + done2 = true; + }); - evb1.reset(); - EXPECT_TRUE(done1); + EXPECT_FALSE(done1); + EXPECT_FALSE(done2); - evb2.reset(); + evb1.reset(); + EXPECT_TRUE(done1); + EXPECT_FALSE(done2); + } EXPECT_TRUE(done2); } +TEST(TimedMutex, ThreadFiberDeadlockOrder) { + folly::EventBase evb; + auto& fm = getFiberManager(evb); + TimedMutex mutex; + + mutex.lock(); + std::thread unlockThread([&] { + /* sleep override */ std::this_thread::sleep_for( + std::chrono::milliseconds{100}); + mutex.unlock(); + }); + + fm.addTask([&] { std::lock_guard lg(mutex); }); + fm.addTask([&] { + runInMainContext([&] { + auto locked = mutex.timed_lock(std::chrono::seconds{1}); + EXPECT_TRUE(locked); + if (locked) { + mutex.unlock(); + } + }); + }); + + evb.loopOnce(); + EXPECT_EQ(0, fm.hasTasks()); + + unlockThread.join(); +} + +TEST(TimedMutex, ThreadFiberDeadlockRace) { + folly::EventBase evb; + auto& fm = getFiberManager(evb); + TimedMutex mutex; + + mutex.lock(); + + fm.addTask([&] { + auto locked = mutex.timed_lock(std::chrono::seconds{1}); + EXPECT_TRUE(locked); + if (locked) { + mutex.unlock(); + } + }); + fm.addTask([&] { + mutex.unlock(); + runInMainContext([&] { + auto locked = mutex.timed_lock(std::chrono::seconds{1}); + EXPECT_TRUE(locked); + if (locked) { + mutex.unlock(); + } + }); + }); + + evb.loopOnce(); + EXPECT_EQ(0, fm.hasTasks()); +} + /** * Test that we can properly track fiber stack usage. *