Jiri Danek created PROTON-1591:
----------------------------------

             Summary: [proton-cpp] Scheduling task from a scheduled task will 
deadlock
                 Key: PROTON-1591
                 URL: https://issues.apache.org/jira/browse/PROTON-1591
             Project: Qpid Proton
          Issue Type: Bug
          Components: cpp-binding
         Environment: commit 6a57a8c986fbf86ad8ad109d673a89a5ae84c544 
(upstream/master)
Author: Cliff Jansen <cliffjan...@apache.org>
Date:   Thu Sep 14 23:29:14 2017 -0700

    PROTON-1349: completed and improved implementation, but still fails many 
tests
            Reporter: Jiri Danek
            Assignee: Cliff Jansen


Modify the {{cpp/simple_send.cpp}} example the following way

{code}
diff --git a/examples/cpp/simple_send.cpp b/examples/cpp/simple_send.cpp
index a4c2272d..92e60ee0 100644
--- a/examples/cpp/simple_send.cpp
+++ b/examples/cpp/simple_send.cpp
@@ -29,9 +29,11 @@
 #include <proton/messaging_handler.hpp>
 #include <proton/tracker.hpp>
 #include <proton/types.hpp>
+#include <proton/work_queue.hpp>
 
 #include <iostream>
 #include <map>
+#include <functional>
 
 #include "fake_cpp11.hpp"
 
@@ -45,15 +47,28 @@ class simple_send : public proton::messaging_handler {
     int confirmed;
     int total;
 
+    std::function<void()> callback;
+
   public:
     simple_send(const std::string &s, const std::string &u, const std::string 
&p, int c) :
-        url(s), user(u), password(p), sent(0), confirmed(0), total(c) {}
+        url(s), user(u), password(p), sent(0), confirmed(0), total(c) {
+        callback = [this]() {
+            std::cout << "Entering callback" << std::endl;
+//            TODO: uncomment one of the two commands below
+//****************************************************************************************************
+//            sender.container().stop();
+//            sender.container().schedule(1 * proton::duration::SECOND, 
proton::work(callback));
+//****************************************************************************************************
+            std::cout << "Leaving callback" << std::endl;
+        };
+    }
 
     void on_container_start(proton::container &c) OVERRIDE {
         proton::connection_options co;
         if (!user.empty()) co.user(user);
         if (!password.empty()) co.password(password);
         sender = c.open_sender(url, co);
+        c.schedule(1 * proton::duration::SECOND, proton::work(callback));
     }
 
     void on_sendable(proton::sender &s) OVERRIDE {
{code}

Now uncomment one of the two commented out commands. Either to stop the 
container from the inside scheduled task, or to schedule new task from inside 
the scheduled task. When executed, the program will deadlock.

{noformat}
Program received signal SIGINT, Interrupt.
0x00007ffff68ef6dc in __lll_lock_wait () from 
/nix/store/l48biijfr1j6d5kdg911051x2phfjrz7-glibc-2.25/lib/libpthread.so.0
(gdb) bt
#0  0x00007ffff68ef6dc in __lll_lock_wait () from 
/nix/store/l48biijfr1j6d5kdg911051x2phfjrz7-glibc-2.25/lib/libpthread.so.0
#1  0x00007ffff68e88e5 in pthread_mutex_lock () from 
/nix/store/l48biijfr1j6d5kdg911051x2phfjrz7-glibc-2.25/lib/libpthread.so.0
#2  0x00007ffff7baf1e8 in __gthread_mutex_lock (__mutex=0x61e148) at 
/nix/store/pdidaf83cvkrgx8xjgjdnl5m1naqjbfk-gcc-7.1.0/include/c++/7.1.0/x86_64-pc-linux-gnu/bits/gthr-default.h:748
#3  std::mutex::lock (this=0x61e148) at 
/nix/store/pdidaf83cvkrgx8xjgjdnl5m1naqjbfk-gcc-7.1.0/include/c++/7.1.0/bits/std_mutex.h:103
#4  std::lock_guard<std::mutex>::lock_guard (__m=..., this=<synthetic pointer>) 
at 
/nix/store/pdidaf83cvkrgx8xjgjdnl5m1naqjbfk-gcc-7.1.0/include/c++/7.1.0/bits/std_mutex.h:162
#5  proton::container::impl::schedule (this=this@entry=0x61e140, delay=..., 
delay@entry=..., f=...) at 
/home/jdanek/Work/repos/qpid-proton/proton-c/bindings/cpp/src/proactor_container_impl.cpp:399
#6  0x00007ffff7baccc8 in proton::container::schedule 
(this=this@entry=0x7fffffffc668, d=..., f=...) at 
/home/jdanek/Work/repos/qpid-proton/proton-c/bindings/cpp/src/container.cpp:109
#7  0x00000000004065f9 in 
simple_send::simple_send(std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const&, 
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > 
const&, std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> > const&, int)::{lambda()#1}::operator()() const 
(__closure=<optimized out>) at 
/home/jdanek/Work/repos/qpid-proton/examples/cpp/simple_send.cpp:58
#8  std::_Function_handler<void (), 
simple_send::simple_send(std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const&, 
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > 
const&, std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> > const&, int)::{lambda()#1}>::_M_invoke(std::_Any_data 
const&) (__functor=...) at 
/nix/store/pdidaf83cvkrgx8xjgjdnl5m1naqjbfk-gcc-7.1.0/include/c++/7.1.0/bits/std_function.h:316
#9  0x00007ffff7baf706 in std::function<void ()>::operator()() const 
(this=<optimized out>) at 
/nix/store/pdidaf83cvkrgx8xjgjdnl5m1naqjbfk-gcc-7.1.0/include/c++/7.1.0/bits/std_function.h:706
#10 proton::work::operator() (this=<optimized out>) at 
/home/jdanek/Work/repos/qpid-proton/proton-c/bindings/cpp/include/proton/work_queue.hpp:59
#11 proton::container::impl::run_timer_jobs (this=this@entry=0x61e140) at 
/home/jdanek/Work/repos/qpid-proton/proton-c/bindings/cpp/src/proactor_container_impl.cpp:439
#12 0x00007ffff7bafe10 in proton::container::impl::handle 
(this=this@entry=0x61e140, event=0x625590) at 
/home/jdanek/Work/repos/qpid-proton/proton-c/bindings/cpp/src/proactor_container_impl.cpp:478
#13 0x00007ffff7baffeb in proton::container::impl::thread 
(this=this@entry=0x61e140) at 
/home/jdanek/Work/repos/qpid-proton/proton-c/bindings/cpp/src/proactor_container_impl.cpp:613
#14 0x00007ffff7bb0393 in proton::container::impl::run (this=0x61e140, 
threads=threads@entry=1) at 
/home/jdanek/Work/repos/qpid-proton/proton-c/bindings/cpp/src/proactor_container_impl.cpp:651
#15 0x00007ffff7bac74d in proton::container::run 
(this=this@entry=0x7fffffffc668) at 
/home/jdanek/Work/repos/qpid-proton/proton-c/bindings/cpp/src/container.cpp:83
#16 0x0000000000404d2f in main (argc=<optimized out>, argv=<optimized out>) at 
/home/jdanek/Work/repos/qpid-proton/examples/cpp/simple_send.cpp:115
#17 0x00007ffff6b1d530 in __libc_start_main () from 
/nix/store/l48biijfr1j6d5kdg911051x2phfjrz7-glibc-2.25/lib/libc.so.6
#18 0x00000000004051aa in _start () at ../sysdeps/x86_64/start.S:120
{noformat}

The lock was first acquired here

{noformat}
(gdb) frame 12
#12 0x00007ffff7bafe10 in proton::container::impl::handle 
(this=this@entry=0x61e140, event=0x625590) at 
/home/jdanek/Work/repos/qpid-proton/proton-c/bindings/cpp/src/proactor_container_impl.cpp:478
478                 run_timer_jobs();
(gdb) l
473     
474         case PN_PROACTOR_TIMEOUT: {
475             GUARD(lock_);
476             // Can get an immediate timeout, if we have a container event 
loop inject
477             if  ( deferred_.size()>0 ) {
478                 run_timer_jobs();
479             }
480     
481             // Run every container event loop job
482             // This is not at all efficient and single threads all these 
jobs, but it does correctly
{noformat}

and the thread tries to reacquire it again here (this is the schedule task from 
scheduled task case)

{noformat}
(gdb) frame 5
#5  proton::container::impl::schedule (this=this@entry=0x61e140, delay=..., 
delay@entry=..., f=...) at 
/home/jdanek/Work/repos/qpid-proton/proton-c/bindings/cpp/src/proactor_container_impl.cpp:399
399         GUARD(lock_);
(gdb) l
394         lc.listen_handler_ = &lh;
395         return proton::listener(listener);
396     }
397     
398     void container::impl::schedule(duration delay, work f) {
399         GUARD(lock_);
400         timestamp now = timestamp::now();
401     
402         // Record timeout; Add callback to timeout sorted list
403         scheduled s = {now+delay, f};
{noformat}

This reproducer is based on larger application which was using the previous 
version of the task scheduling API and which was now updated to compile with 
Proton 0.18.



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@qpid.apache.org
For additional commands, e-mail: dev-h...@qpid.apache.org

Reply via email to