libzmq: Global static mutex random_sync causes order of destruction bug

Issue description

When using zmqpp with libzmq 4.2.3 there is an order of destruction bug in static builds if there are contexts defined globally/static. This is due to the global static mutex random_sync in random.cpp being destructed before the context is destructed.

I think the better approach would be to have client application control the initialization of sodium_init() via the zmq::random_open()/close() function. Client code would need to call this at start/end of main(). I think adding a couple functions like zmq_init() and zmq_destroy() to wrap these kind of init calls would do the trick.

Environment

  • libzmq version (commit hash if unreleased): 4.2.3
  • OS: Ubuntu 16.04

What’s the actual result? (include assertion message & call stack if applicable)

Program received signal SIGABRT, Aborted.
0x00007ffff5534428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
54	../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) list
49	in ../sysdeps/unix/sysv/linux/raise.c
(gdb) bt
#0  0x00007ffff5534428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007ffff553602a in __GI_abort () at abort.c:89
#2  0x00000000012f39ee in zmq::zmq_abort (errmsg_=errmsg_@entry=0x7ffff568c10a "Invalid argument") at src/err.cpp:87
#3  0x00000000012fde65 in zmq::mutex_t::lock (this=0x4431200 <random_sync>) at src/mutex.hpp:122
#4  zmq::scoped_lock_t::scoped_lock_t (mutex_=..., this=<synthetic pointer>) at src/mutex.hpp:168
#5  zmq::random_close () at src/random.cpp:110
#6  0x00000000012ee546 in zmq::ctx_t::~ctx_t (this=0x61600000f980, __in_chrg=<optimized out>) at src/ctx.cpp:124
#7  0x00000000012eeb65 in zmq::ctx_t::terminate (this=0x61600000f980) at src/ctx.cpp:201
#8  0x00000000012dc711 in zmqpp::context::terminate() ()
#9  0x0000000000485eef in zmqpp::context::~context (this=0x4431188 <zmqpp::actor::actor_pipe_ctx_>, __in_chrg=<optimized out>) at ../../../../trunk/thirdparty/zmqpp4.2.0/include/zmqpp/context.hpp:100
#10 0x00007ffff5538ff8 in __run_exit_handlers (status=0, listp=0x7ffff58c35f8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true) at exit.c:82
#11 0x00007ffff5539045 in __GI_exit (status=<optimized out>) at exit.c:104
#12 0x00007ffff551f837 in __libc_start_main (main=0x4792c0 <main(int, char**)>, argc=2, argv=0x7fffffffdb58, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdb48) at ../csu/libc-start.c:325
#13 0x00000000004463a9 in _start ()

What’s the expected result?

Correct order of destruction and no abort being thrown.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 32 (29 by maintainers)

Commits related to this issue

Most upvoted comments

@sigiesec I tried an implementation on Windows - tests seems to pass, could you please have a quick look and let me know if it would work? It uses a static CriticalSection and it initialises it with InitOnceExecuteOnce:

https://github.com/bluca/libzmq/commit/d0602f08952c35e3e42506d9685f8e21c9c52057