zeromq / libzmq

ZeroMQ core engine in C++, implements ZMTP/3.1
https://www.zeromq.org
Mozilla Public License 2.0
9.8k stars 2.36k forks source link

zmq threads use default stack size, and can overflow the stack #2543

Open mmclin opened 7 years ago

mmclin commented 7 years ago

On the Windows OS, processes typically receive 1MB stack size when requesting the default stack size, which is what zmq is doing.

However, applications are able to change the default that is used for all subsequent threads that are created, by specifying a STACKSIZE rule in a .def file. https://msdn.microsoft.com/en-us/library/28d6s79h.aspx

If an application picks a smaller stack size, say 400KB (as ours did), this results in the zmq threads also being limited to this stack size, in which case zmq consistently overflows the stack during initialization in one of its threads when zmq_socket() is called.

We have confirmed that by increasing our default stack size to 1MB the overflow in zmq goes away. Therefore, it appears that zmq has a significant stack size requirement for at least some of its threads, and should not be requesting a default size, but instead should explicitly request a stack size that is safe for its usage.

Although we have a workaround, I see this as a bug in zmq, since a library should not assume anything about the default stack size of its parent process.

bluca commented 7 years ago

This requirement is documented here: https://github.com/zeromq/libzmq/blob/master/INSTALL#L49

mmclin commented 7 years ago

In our case, VS2013 was used. I'm not sure if this std::map implementation is improved in VS2013 compared to VS2012. In any case, wouldn't the correct approach be to adapt the cmake script to set OS and compiler-specific defines that affect the stack size requested when zmq creates threads?

The situation is especially problematic if we use ZMQ in a DLL which is distributed to third-parties (i.e., apps out of our control), in which case we cannot know what the default stack limit will be.

bluca commented 7 years ago

It's not only 2012 according to that page:

In all Windows builds it is recommended to start with at least 2 MB stack size unless application using ZeroMQ is using large number of threads which can cause substantial consumption of virtual address space, especially if 32 bit build is used.

Also you'll have problems in your thread too when calling zmq_poll as it has the same requirement

If you have a solution through the build scripts feel free to send a PR

bjovke commented 7 years ago

@mmclin Yes, you're right that libzmq could set stack size for it's internal threads. But I wouldn't call this a bug but more a feature which could be implemented. You're free to create PR for this. You still have to set stack size of main thread when you use libzmq api. You can try overriding FD_SETSIZE and setting it to lower value than default 16384 set by libzmq if you're not using many sockets. This would lower stack consumption.

mmclin commented 7 years ago

OK, we will need to address this in the coming month or two. If we resolve it on zmq side, I'll push up a PR.