libzmq
libzmq copied to clipboard
RADIO socket with multple connects cores when using large group names
Issue description
Application with a ZMQ RADIO socket cores after what looks like as a heap corruption. The application only crashes if the RADIO socket is connected to more than one endpoint and the group length is greater than 14 bytes.
$ ./zmq-radio-test
connect to udp://localhost:25680
connect to udp://localhost:25681
........malloc(): mismatching next->prev_size (unsorted)
Aborted (core dumped)
Environment
- libzmq version (commit hash if unreleased): The crash occurs with d7e439d3366c5100547262890a077f2e99aa0784 and v4.3.4 (only tested with these).
- OS: Tested on Ubuntu 18.04 LTS, CentOS 8, and F33. Crash occurs on all.
Minimal test code / Steps to reproduce the issue
- Use the following example code to reproduce. It has enough features to reproduce the issue: multiple radio connects and performing dynamic allocation as part of its algorithm. Note: sample code leaks heap allocation on purpose to make sure allocations exist between zmq calls. Crash occurs within a few seconds.
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <zmq.h>
int main(int,char *[])
{
void * pCtx{};
void * pRadio{};
if(!(pCtx = zmq_ctx_new()))
{
std::cerr<<zmq_strerror(errno)<<std::endl;
return EXIT_FAILURE;
}
if(!(pRadio = zmq_socket(pCtx,ZMQ_RADIO)))
{
std::cerr<<zmq_strerror(errno)<<std::endl;
return EXIT_FAILURE;
}
int iConnections{2};
// create multple RADIO connections, will not crash if you only have
// a single connection
for(int i = 0; i < iConnections; ++i)
{
std::string s{"udp://localhost:"};
if(zmq_connect(pRadio,std::string(s + std::to_string(25680 + i)).c_str()))
{
std::cerr<<zmq_strerror(errno)<<std::endl;
return EXIT_FAILURE;
}
else
{
std::cout<<"connect to udp://localhost:"<<25680+i<<std::endl;
}
}
while(1)
{
const char d[] = "abcdefghijklmnopqrstuvwxyz";
zmq_msg_t message;
zmq_msg_init_size(&message,strlen(d));
memcpy(zmq_msg_data(&message),
d,
strlen(d));
// use a group name > 14 to trigger use of group_t's long_group_t
zmq_msg_set_group(&message,"alphabet1234567890");
zmq_msg_send(&message,pRadio,0);
// do not deallocate so to emulate an application making heap
// allocations intermixed with zmq msg sends
auto foo = new char[64];
// do some action on the memory
std::memset(foo,0xff,64);
std::cerr<<".";
sleep(1);
// not deallocate, see above
//delete [] foo;
}
return EXIT_SUCCESS;
}
- Compile and run test application.
$ ./zmq-radio-test
What's the actual result? (include assertion message & call stack if applicable)
Prior to crashing the application emits the following libc message:
malloc(): mismatching next->prev_size (unsorted)
Backtrace on the core:
(gdb) bt
#0 0x00007f626ba8a9e5 in raise () from /lib64/libc.so.6
#1 0x00007f626ba738a4 in abort () from /lib64/libc.so.6
#2 0x00007f626bacd007 in __libc_message () from /lib64/libc.so.6
#3 0x00007f626bad4cdc in malloc_printerr () from /lib64/libc.so.6
#4 0x00007f626bad844c in _int_malloc () from /lib64/libc.so.6
#5 0x00007f626bad98a1 in malloc () from /lib64/libc.so.6
#6 0x00007f626bfca38a in zmq::msg_t::set_group (length_=18, group_=0x40203e "alphabet1234567890", this=0x7ffff079cd40) at src/msg.cpp:700
#7 zmq::msg_t::set_group (this=0x7ffff079cd40, group_=0x40203e "alphabet1234567890", length_=18) at src/msg.cpp:690
#8 0x00000000004015e2 in main ()
Running through valgrind reports invalid reads when running the example application as included:
==309424== ERROR SUMMARY: 100 errors from 10 contexts (suppressed: 0 from 0)
==309424==
==309424== 1 errors in context 1 of 10:
==309424== Invalid read of size 2
==309424== at 0x4840610: memmove (vg_replace_strmem.c:1270)
==309424== by 0x4890CFD: pull_msg (radio.cpp:271)
==309424== by 0x4890CFD: zmq::radio_session_t::pull_msg(zmq::msg_t*) (radio.cpp:257)
==309424== by 0x48B4328: zmq::udp_engine_t::out_event() (udp_engine.cpp:440)
==309424== by 0x48758BF: zmq::epoll_t::loop() (epoll.cpp:202)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Address 0x4ec1bb0 is 16 bytes inside a block of size 264 free'd
==309424== at 0x483A9F5: free (vg_replace_malloc.c:538)
==309424== by 0x48806BA: zmq::msg_t::close() (msg.cpp:322)
==309424== by 0x48B43D5: zmq::udp_engine_t::out_event() (udp_engine.cpp:483)
==309424== by 0x48758BF: zmq::epoll_t::loop() (epoll.cpp:202)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Block was alloc'd at
==309424== at 0x4839809: malloc (vg_replace_malloc.c:307)
==309424== by 0x4881389: set_group (msg.cpp:700)
==309424== by 0x4881389: zmq::msg_t::set_group(char const*, unsigned long) (msg.cpp:690)
==309424== by 0x4015E1: main (in /home/me/dev/scratch/zmq-radio-test/zmq-radio-test)
==309424==
==309424==
==309424== 1 errors in context 2 of 10:
==309424== Invalid read of size 1
==309424== at 0x483CB86: strlen (vg_replace_strmem.c:459)
==309424== by 0x4890CC8: pull_msg (radio.cpp:265)
==309424== by 0x4890CC8: zmq::radio_session_t::pull_msg(zmq::msg_t*) (radio.cpp:257)
==309424== by 0x48B4328: zmq::udp_engine_t::out_event() (udp_engine.cpp:440)
==309424== by 0x48758BF: zmq::epoll_t::loop() (epoll.cpp:202)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Address 0x4ec1ba0 is 0 bytes inside a block of size 264 free'd
==309424== at 0x483A9F5: free (vg_replace_malloc.c:538)
==309424== by 0x48806BA: zmq::msg_t::close() (msg.cpp:322)
==309424== by 0x48B43D5: zmq::udp_engine_t::out_event() (udp_engine.cpp:483)
==309424== by 0x48758BF: zmq::epoll_t::loop() (epoll.cpp:202)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Block was alloc'd at
==309424== at 0x4839809: malloc (vg_replace_malloc.c:307)
==309424== by 0x4881389: set_group (msg.cpp:700)
==309424== by 0x4881389: zmq::msg_t::set_group(char const*, unsigned long) (msg.cpp:690)
==309424== by 0x4015E1: main (in /home/me/dev/scratch/zmq-radio-test/zmq-radio-test)
==309424==
==309424==
==309424== 2 errors in context 3 of 10:
==309424== Invalid read of size 8
==309424== at 0x48405BD: memmove (vg_replace_strmem.c:1270)
==309424== by 0x4890CFD: pull_msg (radio.cpp:271)
==309424== by 0x4890CFD: zmq::radio_session_t::pull_msg(zmq::msg_t*) (radio.cpp:257)
==309424== by 0x48B4328: zmq::udp_engine_t::out_event() (udp_engine.cpp:440)
==309424== by 0x48758BF: zmq::epoll_t::loop() (epoll.cpp:202)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Address 0x4ec1ba0 is 0 bytes inside a block of size 264 free'd
==309424== at 0x483A9F5: free (vg_replace_malloc.c:538)
==309424== by 0x48806BA: zmq::msg_t::close() (msg.cpp:322)
==309424== by 0x48B43D5: zmq::udp_engine_t::out_event() (udp_engine.cpp:483)
==309424== by 0x48758BF: zmq::epoll_t::loop() (epoll.cpp:202)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Block was alloc'd at
==309424== at 0x4839809: malloc (vg_replace_malloc.c:307)
==309424== by 0x4881389: set_group (msg.cpp:700)
==309424== by 0x4881389: zmq::msg_t::set_group(char const*, unsigned long) (msg.cpp:690)
==309424== by 0x4015E1: main (in /home/me/dev/scratch/zmq-radio-test/zmq-radio-test)
==309424==
==309424==
==309424== 3 errors in context 4 of 10:
==309424== Invalid read of size 2
==309424== at 0x4840610: memmove (vg_replace_strmem.c:1270)
==309424== by 0x4890CFD: pull_msg (radio.cpp:271)
==309424== by 0x4890CFD: zmq::radio_session_t::pull_msg(zmq::msg_t*) (radio.cpp:257)
==309424== by 0x48B4328: zmq::udp_engine_t::out_event() (udp_engine.cpp:440)
==309424== by 0x4877913: zmq::io_thread_t::in_event() (io_thread.cpp:91)
==309424== by 0x48758D5: zmq::epoll_t::loop() (epoll.cpp:206)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Address 0x4ecaad0 is 16 bytes inside a block of size 264 free'd
==309424== at 0x483A9F5: free (vg_replace_malloc.c:538)
==309424== by 0x48806BA: zmq::msg_t::close() (msg.cpp:322)
==309424== by 0x48B43D5: zmq::udp_engine_t::out_event() (udp_engine.cpp:483)
==309424== by 0x4877913: zmq::io_thread_t::in_event() (io_thread.cpp:91)
==309424== by 0x48758D5: zmq::epoll_t::loop() (epoll.cpp:206)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Block was alloc'd at
==309424== at 0x4839809: malloc (vg_replace_malloc.c:307)
==309424== by 0x4881389: set_group (msg.cpp:700)
==309424== by 0x4881389: zmq::msg_t::set_group(char const*, unsigned long) (msg.cpp:690)
==309424== by 0x4015E1: main (in /home/me/dev/scratch/zmq-radio-test/zmq-radio-test)
==309424==
==309424==
==309424== 3 errors in context 5 of 10:
==309424== Invalid read of size 1
==309424== at 0x483CB86: strlen (vg_replace_strmem.c:459)
==309424== by 0x4890CC8: pull_msg (radio.cpp:265)
==309424== by 0x4890CC8: zmq::radio_session_t::pull_msg(zmq::msg_t*) (radio.cpp:257)
==309424== by 0x48B4328: zmq::udp_engine_t::out_event() (udp_engine.cpp:440)
==309424== by 0x4877913: zmq::io_thread_t::in_event() (io_thread.cpp:91)
==309424== by 0x48758D5: zmq::epoll_t::loop() (epoll.cpp:206)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Address 0x4ecaac0 is 0 bytes inside a block of size 264 free'd
==309424== at 0x483A9F5: free (vg_replace_malloc.c:538)
==309424== by 0x48806BA: zmq::msg_t::close() (msg.cpp:322)
==309424== by 0x48B43D5: zmq::udp_engine_t::out_event() (udp_engine.cpp:483)
==309424== by 0x4877913: zmq::io_thread_t::in_event() (io_thread.cpp:91)
==309424== by 0x48758D5: zmq::epoll_t::loop() (epoll.cpp:206)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Block was alloc'd at
==309424== at 0x4839809: malloc (vg_replace_malloc.c:307)
==309424== by 0x4881389: set_group (msg.cpp:700)
==309424== by 0x4881389: zmq::msg_t::set_group(char const*, unsigned long) (msg.cpp:690)
==309424== by 0x4015E1: main (in /home/me/dev/scratch/zmq-radio-test/zmq-radio-test)
==309424==
==309424==
==309424== 3 errors in context 6 of 10:
==309424== Invalid read of size 4
==309424== at 0x48806A4: zmq::msg_t::close() (msg.cpp:317)
==309424== by 0x48B43D5: zmq::udp_engine_t::out_event() (udp_engine.cpp:483)
==309424== by 0x48758BF: zmq::epoll_t::loop() (epoll.cpp:202)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Address 0x4ec1ca0 is 256 bytes inside a block of size 264 free'd
==309424== at 0x483A9F5: free (vg_replace_malloc.c:538)
==309424== by 0x48806BA: zmq::msg_t::close() (msg.cpp:322)
==309424== by 0x48B43D5: zmq::udp_engine_t::out_event() (udp_engine.cpp:483)
==309424== by 0x48758BF: zmq::epoll_t::loop() (epoll.cpp:202)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Block was alloc'd at
==309424== at 0x4839809: malloc (vg_replace_malloc.c:307)
==309424== by 0x4881389: set_group (msg.cpp:700)
==309424== by 0x4881389: zmq::msg_t::set_group(char const*, unsigned long) (msg.cpp:690)
==309424== by 0x4015E1: main (in /home/me/dev/scratch/zmq-radio-test/zmq-radio-test)
==309424==
==309424==
==309424== 6 errors in context 7 of 10:
==309424== Invalid read of size 8
==309424== at 0x48405BD: memmove (vg_replace_strmem.c:1270)
==309424== by 0x4890CFD: pull_msg (radio.cpp:271)
==309424== by 0x4890CFD: zmq::radio_session_t::pull_msg(zmq::msg_t*) (radio.cpp:257)
==309424== by 0x48B4328: zmq::udp_engine_t::out_event() (udp_engine.cpp:440)
==309424== by 0x4877913: zmq::io_thread_t::in_event() (io_thread.cpp:91)
==309424== by 0x48758D5: zmq::epoll_t::loop() (epoll.cpp:206)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Address 0x4ecaac0 is 0 bytes inside a block of size 264 free'd
==309424== at 0x483A9F5: free (vg_replace_malloc.c:538)
==309424== by 0x48806BA: zmq::msg_t::close() (msg.cpp:322)
==309424== by 0x48B43D5: zmq::udp_engine_t::out_event() (udp_engine.cpp:483)
==309424== by 0x4877913: zmq::io_thread_t::in_event() (io_thread.cpp:91)
==309424== by 0x48758D5: zmq::epoll_t::loop() (epoll.cpp:206)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Block was alloc'd at
==309424== at 0x4839809: malloc (vg_replace_malloc.c:307)
==309424== by 0x4881389: set_group (msg.cpp:700)
==309424== by 0x4881389: zmq::msg_t::set_group(char const*, unsigned long) (msg.cpp:690)
==309424== by 0x4015E1: main (in /home/me/dev/scratch/zmq-radio-test/zmq-radio-test)
==309424==
==309424==
==309424== 9 errors in context 8 of 10:
==309424== Invalid read of size 4
==309424== at 0x48806A4: zmq::msg_t::close() (msg.cpp:317)
==309424== by 0x48B43D5: zmq::udp_engine_t::out_event() (udp_engine.cpp:483)
==309424== by 0x4877913: zmq::io_thread_t::in_event() (io_thread.cpp:91)
==309424== by 0x48758D5: zmq::epoll_t::loop() (epoll.cpp:206)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Address 0x4ecabc0 is 256 bytes inside a block of size 264 free'd
==309424== at 0x483A9F5: free (vg_replace_malloc.c:538)
==309424== by 0x48806BA: zmq::msg_t::close() (msg.cpp:322)
==309424== by 0x48B43D5: zmq::udp_engine_t::out_event() (udp_engine.cpp:483)
==309424== by 0x4877913: zmq::io_thread_t::in_event() (io_thread.cpp:91)
==309424== by 0x48758D5: zmq::epoll_t::loop() (epoll.cpp:206)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Block was alloc'd at
==309424== at 0x4839809: malloc (vg_replace_malloc.c:307)
==309424== by 0x4881389: set_group (msg.cpp:700)
==309424== by 0x4881389: zmq::msg_t::set_group(char const*, unsigned long) (msg.cpp:690)
==309424== by 0x4015E1: main (in /home/me/dev/scratch/zmq-radio-test/zmq-radio-test)
==309424==
==309424==
==309424== 18 errors in context 9 of 10:
==309424== Invalid read of size 1
==309424== at 0x483CB94: strlen (vg_replace_strmem.c:459)
==309424== by 0x4890CC8: pull_msg (radio.cpp:265)
==309424== by 0x4890CC8: zmq::radio_session_t::pull_msg(zmq::msg_t*) (radio.cpp:257)
==309424== by 0x48B4328: zmq::udp_engine_t::out_event() (udp_engine.cpp:440)
==309424== by 0x48758BF: zmq::epoll_t::loop() (epoll.cpp:202)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Address 0x4ec1ba1 is 1 bytes inside a block of size 264 free'd
==309424== at 0x483A9F5: free (vg_replace_malloc.c:538)
==309424== by 0x48806BA: zmq::msg_t::close() (msg.cpp:322)
==309424== by 0x48B43D5: zmq::udp_engine_t::out_event() (udp_engine.cpp:483)
==309424== by 0x48758BF: zmq::epoll_t::loop() (epoll.cpp:202)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Block was alloc'd at
==309424== at 0x4839809: malloc (vg_replace_malloc.c:307)
==309424== by 0x4881389: set_group (msg.cpp:700)
==309424== by 0x4881389: zmq::msg_t::set_group(char const*, unsigned long) (msg.cpp:690)
==309424== by 0x4015E1: main (in /home/me/dev/scratch/zmq-radio-test/zmq-radio-test)
==309424==
==309424==
==309424== 54 errors in context 10 of 10:
==309424== Invalid read of size 1
==309424== at 0x483CB94: strlen (vg_replace_strmem.c:459)
==309424== by 0x4890CC8: pull_msg (radio.cpp:265)
==309424== by 0x4890CC8: zmq::radio_session_t::pull_msg(zmq::msg_t*) (radio.cpp:257)
==309424== by 0x48B4328: zmq::udp_engine_t::out_event() (udp_engine.cpp:440)
==309424== by 0x4877913: zmq::io_thread_t::in_event() (io_thread.cpp:91)
==309424== by 0x48758D5: zmq::epoll_t::loop() (epoll.cpp:206)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Address 0x4ecaac1 is 1 bytes inside a block of size 264 free'd
==309424== at 0x483A9F5: free (vg_replace_malloc.c:538)
==309424== by 0x48806BA: zmq::msg_t::close() (msg.cpp:322)
==309424== by 0x48B43D5: zmq::udp_engine_t::out_event() (udp_engine.cpp:483)
==309424== by 0x4877913: zmq::io_thread_t::in_event() (io_thread.cpp:91)
==309424== by 0x48758D5: zmq::epoll_t::loop() (epoll.cpp:206)
==309424== by 0x48AF057: thread_routine (thread.cpp:256)
==309424== by 0x4E733F8: ??? (in /usr/lib64/libpthread-2.32.so)
==309424== by 0x4D724C2: clone (in /usr/lib64/libc-2.32.so)
==309424== Block was alloc'd at
==309424== at 0x4839809: malloc (vg_replace_malloc.c:307)
==309424== by 0x4881389: set_group (msg.cpp:700)
==309424== by 0x4881389: zmq::msg_t::set_group(char const*, unsigned long) (msg.cpp:690)
==309424== by 0x4015E1: main (in /home/me/dev/scratch/zmq-radio-test/zmq-radio-test)
==309424==
==309424== ERROR SUMMARY: 100 errors from 10 contexts (suppressed: 0 from 0)
If you modify the example application and change the number of connections to 1, there is no crash and valgrind reports no invalid reads:
--- zmq-radio-test.cc 2021-05-27 14:12:03.887771023 -0400
+++ zmq-radio-test.cc.1-connect 2021-05-27 14:13:09.857747179 -0400
@@ -21,7 +21,7 @@
return EXIT_FAILURE;
}
- int iConnections{2};
+ int iConnections{1};
// create multple RADIO connections, will not crash if you only have
// a single connection
What's the expected result?
Normal operation. No crash.
I just encountered this exact issue. Radio/Dish crashes on send only with multiple connections and group names longer then 14 Bytes. zeromq/4.3.4 with draft Draft API.
Presumably its something to do with this code from msg.cpp. Seems to be only when tripping that (length > 14) condition
int zmq::msg_t::set_group (const char *group_, size_t length_)
{
if (length_ > ZMQ_GROUP_MAX_LENGTH) {
errno = EINVAL;
return -1;
}
if (length_ > 14) {
_u.base.group.lgroup.type = group_type_long;
_u.base.group.lgroup.content =
(long_group_t *) malloc (sizeof (long_group_t));
assert (_u.base.group.lgroup.content);
new (&_u.base.group.lgroup.content->refcnt) zmq::atomic_counter_t ();
_u.base.group.lgroup.content->refcnt.set (1);
strncpy (_u.base.group.lgroup.content->group, group_, length_);
_u.base.group.lgroup.content->group[length_] = '\0';
} else {
strncpy (_u.base.group.sgroup.group, group_, length_);
_u.base.group.sgroup.group[length_] = '\0';
}
return 0;
}