Skip to content

Commit 183d8ab

Browse files
committed
add lock to http linux listener to fix race condition
1 parent f364f32 commit 183d8ab

File tree

1 file changed

+21
-18
lines changed

1 file changed

+21
-18
lines changed

Release/src/http/listener/http_linux_server.cpp

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -570,15 +570,15 @@ void hostport_listener::stop()
570570

571571
void hostport_listener::add_listener(const std::string& path, http_listener* listener)
572572
{
573-
pplx::extensibility::scoped_read_lock_t lock(m_listeners_lock);
573+
pplx::extensibility::scoped_rw_lock_t lock(m_listeners_lock);
574574

575575
if (!m_listeners.insert(std::map<std::string,http_listener*>::value_type(path, listener)).second)
576576
throw std::invalid_argument("Error: http_listener is already registered for this path");
577577
}
578578

579579
void hostport_listener::remove_listener(const std::string& path, http_listener*)
580580
{
581-
pplx::extensibility::scoped_read_lock_t lock(m_listeners_lock);
581+
pplx::extensibility::scoped_rw_lock_t lock(m_listeners_lock);
582582

583583
if (m_listeners.erase(path) != 1)
584584
throw std::invalid_argument("Error: no http_listener found for this path");
@@ -652,7 +652,7 @@ pplx::task<void> http_linux_server::register_listener(http_listener* listener)
652652
auto path = parts.second;
653653

654654
{
655-
pplx::extensibility::scoped_read_lock_t lock(m_listeners_lock);
655+
pplx::extensibility::scoped_rw_lock_t lock(m_listeners_lock);
656656
if (m_registered_listeners.find(listener) != m_registered_listeners.end())
657657
throw std::invalid_argument("listener already registered");
658658

@@ -679,29 +679,32 @@ pplx::task<void> http_linux_server::unregister_listener(http_listener* listener)
679679
auto parts = canonical_parts(listener->uri());
680680
auto hostport = parts.first;
681681
auto path = parts.second;
682-
// First remove listener registration.
683-
std::unique_ptr<pplx::extensibility::reader_writer_lock_t> pListenerLock;
684-
{
685-
pplx::extensibility::scoped_read_lock_t lock(m_listeners_lock);
686-
{
687-
auto hostport_listeners = m_listeners.find(hostport);
688-
if (hostport_listeners == m_listeners.end())
689-
{
690-
throw std::invalid_argument("Error: no listener registered for that host");
691-
}
692-
693-
hostport_listeners->second->remove_listener(path, listener);
694-
695-
}
682+
// First remove the listener from hostport listener
683+
{
684+
pplx::extensibility::scoped_read_lock_t lock(m_listeners_lock);
685+
auto itr = m_listeners.find(hostport);
686+
if (itr == m_listeners.end())
687+
{
688+
throw std::invalid_argument("Error: no listener registered for that host");
689+
}
690+
691+
itr->second->remove_listener(path, listener);
692+
}
693+
694+
// Second remove the listener form listener collection
695+
std::unique_ptr<pplx::extensibility::reader_writer_lock_t> pListenerLock = nullptr;
696+
{
697+
pplx::extensibility::scoped_rw_lock_t lock(m_listeners_lock);
696698
pListenerLock = std::move(m_registered_listeners[listener]);
697699
m_registered_listeners[listener] = nullptr;
698700
m_registered_listeners.erase(listener);
699701
}
700702

701703
// Then take the listener write lock to make sure there are no calls into the listener's
702704
// request handler.
705+
if (pListenerLock != nullptr)
703706
{
704-
pplx::extensibility::scoped_read_lock_t lock(*pListenerLock);
707+
pplx::extensibility::scoped_rw_lock_t lock(*pListenerLock);
705708
}
706709

707710
return pplx::task_from_result();

0 commit comments

Comments
 (0)