Hi Martin,

On Sat, Nov 13, 2010 at 5:47 PM, Dhammika Pathirana <dhamm...@gmail.com> wrote:
> Hi Martin,
>
> On Sat, Nov 13, 2010 at 2:18 AM, Martin Sustrik <sust...@250bpm.com> wrote:
>> On 11/13/2010 11:13 AM, Dhammika Pathirana wrote:
>>
>>> In finalize_initialization(), we detach the engine and pass it over to
>>> app thread.
>>
>> Actually, it's passed to another I/O thread rather than to the app thread,
>> but that's irrelevant to the problem.
>
> correct, my bad.
>
>
>>
>>>             engine->unplug ();
>>>             send_attach (session, engine, peer_identity, false);
>>>             engine = NULL;
>>>             terminate ();
>>>
>>> But there's a stack reference to this engine object,
>>> engine->out_event() callback.
>>
>> How does the stack look like when the out_event() is called on destroyed
>> engine?
>>
>>> I'll check if this shows up in valgrind.
>>
>
> I added following dbg prints,
>
> @ -51,6 +51,7 @@ zmq::zmq_engine_t::zmq_engine_t (fd_t fd_, const
> options_t &options_) :
>  zmq::zmq_engine_t::~zmq_engine_t ()
>  {
>     zmq_assert (!plugged);
> +    printf("~engine() %p\n", (void *)this);
>  }
>
>  void zmq::zmq_engine_t::plug (io_thread_t *io_thread_, i_inout *inout_)
> @@ -160,6 +161,9 @@ void zmq::zmq_engine_t::out_event ()
>         }
>     }
>
> +    if (!plugged)
> +        printf("engine %p unplugged\n", (void *)this);
> +
>
> stdout just before crash,
>
> engine 0x63e5130 unplugged
> ~engine() 0x63d3320
> ~engine() 0x63dbfa0
> ~engine() 0x63e5130
> ~engine() 0x63f7810
> ~engine() 0x63f3410
> ~engine() 0x63d7bb0
> ~engine() 0x63e0cd0
> engine 0x63f7810 unplugged
> Bad file descriptor
> ~engine() 0x63eefb0
> nbytes != -1 (tcp_socket.cpp:197)
> Killed
>
> Note "~engine() 0x63f7810" before "engine 0x63f7810 unplugged" msg.
> Here's stack trace,
>
> (gdb) bt
> #0  0x0000000005ec8a75 in *__GI_raise (sig=<value optimized out>) at
> ../nptl/sysdeps/unix/sysv/linux/raise.c:64
> #1  0x0000000005ecc5c0 in *__GI_abort () at abort.c:92
> #2  0x0000000004e97962 in zmq::tcp_socket_t::write (this=0x63f7828,
> data=0x63f9a30, size=2) at tcp_socket.cpp:197
> #3  0x0000000004e9fd3b in zmq::zmq_engine_t::out_event
> (this=0x63f7810) at zmq_engine.cpp:169
> #4  0x0000000004e76db3 in zmq::epoll_t::loop (this=0x639b1a0) at epoll.cpp:156
> #5  0x0000000004e76ee2 in zmq::epoll_t::worker_routine
> (arg_=0x639b1a0) at epoll.cpp:173
> #6  0x0000000004e97c9a in zmq::thread_t::thread_routine
> (arg_=0x639b210) at thread.cpp:79
> #7  0x00000000054d09ca in start_thread (arg=<value optimized out>) at
> pthread_create.c:300
> #8  0x0000000005f7b70d in clone () at
> ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
> #9  0x0000000000000000 in ?? ()
> (gdb) fr 3
> #3  0x0000000004e9fd3b in zmq::zmq_engine_t::out_event
> (this=0x63f7810) at zmq_engine.cpp:169
> 169         int nbytes = tcp_socket.write (outpos, outsize);
> (gdb) p this
> $1 = (zmq::zmq_engine_t * const) 0x63f7810
>
>
> I could be reading this wrong, and I had to run it few dozen times to
> get it to crash.
>
>
> Dhammika
>


How about adding a callback to notify when poller is about to destroy
retired event handle?
Something like,
        //  Destroy retired event sources.
        for (retired_t::iterator it = retired.begin (); it !=
retired.end (); it ++) {
            // Notify poller is about to delete poll handle
            (*it)->events->toss();
            delete *it;
        }
        retired.clear ();

Engine can implement toss() to check a refcount, and delete it if
there's no other object referencing it.
This won't affect data path, but will add some overhead to poller loop.


Dhammika
_______________________________________________
zeromq-dev mailing list
zeromq-dev@lists.zeromq.org
http://lists.zeromq.org/mailman/listinfo/zeromq-dev

Reply via email to