Skip to content

Commit

Permalink
bump czmq/libzmq, statically link against them
Browse files Browse the repository at this point in the history
Statically link against libzmq, czmq and libsodium, to avoid issues with
dynamic linking of libzmq (see e.g. methodmissing#43).

Whilst on it (mainly because the existing versions of czmq/libzmq were
being a PITA to get to link statically properly), also bump the versions
of libzmq and czmq.

With czmq now being at API v3, also adjust the extension to be
compatible with it. It still uses a fair number of deprecated APIs, but
it absolutely works with API v3.

Fixes methodmissing#43
Fixes methodmissing#45 (hopefully)
Fixes methodmissing#47
  • Loading branch information
bwalex committed Oct 25, 2015
1 parent d7ce432 commit d782930
Show file tree
Hide file tree
Showing 13 changed files with 168 additions and 66 deletions.
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "ext/zeromq"]
path = ext/zeromq
url = https://github.com/zeromq/zeromq4-x
url = https://github.com/zeromq/libzmq
[submodule "ext/czmq"]
path = ext/czmq
url = https://github.com/zeromq/czmq
Expand Down
2 changes: 1 addition & 1 deletion ext/czmq
Submodule czmq updated 410 files
71 changes: 30 additions & 41 deletions ext/rbczmq/beacon.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@
static VALUE rb_czmq_nogvl_beacon_destroy(void *ptr)
{
zmq_beacon_wrapper *beacon = ptr;

if (beacon->beacon) {
zbeacon_destroy(&beacon->beacon);
zactor_destroy(&beacon->beacon);
beacon->beacon = NULL;
}

if (beacon->hostname) {
zstr_free(&beacon->hostname);
}
return Qnil;
}

Expand All @@ -36,8 +41,16 @@ static void rb_czmq_free_beacon_gc(void *ptr)
*/
static VALUE rb_czmq_nogvl_new_beacon(void *ptr)
{
int port = (int)ptr;
return (VALUE)zbeacon_new(port);
zmq_beacon_wrapper *beacon = ptr;

beacon->beacon = zactor_new(zbeacon, NULL);
beacon->interval = 1000;

zsock_send(beacon->beacon, "si", "CONFIGURE", beacon->port);
beacon->hostname = zstr_recv(beacon->beacon);
assert (beacon->hostname != NULL);

return Qnil;
}

/*
Expand All @@ -53,11 +66,12 @@ static VALUE rb_czmq_nogvl_new_beacon(void *ptr)
static VALUE rb_czmq_beacon_s_new(VALUE beacon, VALUE port)
{
zmq_beacon_wrapper *bcn = NULL;
int prt;
Check_Type(port, T_FIXNUM);
beacon = Data_Make_Struct(rb_cZmqBeacon, zmq_beacon_wrapper, 0, rb_czmq_free_beacon_gc, bcn);
prt = FIX2INT(port);
bcn->beacon = (zbeacon_t*)rb_thread_call_without_gvl(rb_czmq_nogvl_new_beacon, (void *)prt, RUBY_UBF_IO, 0);
bcn->port = FIX2INT(port);
if (bcn->port == 0)
rb_raise(rb_eArgError, "port must not be zero!");
rb_thread_call_without_gvl(rb_czmq_nogvl_new_beacon, (void *)bcn, RUBY_UBF_IO, 0);
ZmqAssertObjOnAlloc(bcn->beacon, bcn);
rb_obj_call_init(beacon, 0, NULL);
return beacon;
Expand Down Expand Up @@ -94,20 +108,7 @@ static VALUE rb_czmq_beacon_destroy(VALUE obj)
static VALUE rb_czmq_beacon_hostname(VALUE obj)
{
GetZmqBeacon(obj);
return rb_str_new2(zbeacon_hostname(beacon->beacon));
}

/*
* :nodoc:
* Set the beacon broadcast interval while the GIL is released.
*
*/
static VALUE rb_czmq_nogvl_set_interval(void *ptr)
{
struct nogvl_beacon_interval_args *args = ptr;
zmq_beacon_wrapper *beacon = args->beacon;
zbeacon_set_interval(beacon->beacon, args->interval);
return Qnil;
return rb_str_new2(beacon->hostname);
}

/*
Expand All @@ -125,21 +126,7 @@ static VALUE rb_czmq_beacon_set_interval(VALUE obj, VALUE interval)
struct nogvl_beacon_interval_args args;
GetZmqBeacon(obj);
Check_Type(interval, T_FIXNUM);
args.beacon = beacon;
args.interval = FIX2INT(interval);
rb_thread_call_without_gvl(rb_czmq_nogvl_set_interval, (void *)&args, RUBY_UBF_IO, 0);
return Qnil;
}

/*
* :nodoc:
* Filter beacons while the GIL is released.
*
*/
static VALUE rb_czmq_nogvl_noecho(void *ptr)
{
zmq_beacon_wrapper *beacon = ptr;
zbeacon_noecho(beacon->beacon);
beacon->interval = FIX2INT(interval);
return Qnil;
}

Expand All @@ -156,7 +143,7 @@ static VALUE rb_czmq_nogvl_noecho(void *ptr)
static VALUE rb_czmq_beacon_noecho(VALUE obj)
{
GetZmqBeacon(obj);
rb_thread_call_without_gvl(rb_czmq_nogvl_noecho, (void *)beacon, RUBY_UBF_IO, 0);
/* XXX: Nothing to do here, as v3 always filters out our own message */
return Qnil;
}

Expand All @@ -169,7 +156,8 @@ static VALUE rb_czmq_nogvl_publish(void *ptr)
{
struct nogvl_beacon_publish_args *args = ptr;
zmq_beacon_wrapper *beacon = args->beacon;
zbeacon_publish(beacon->beacon, (byte *)args->transmit ,args->length);
zsock_send(beacon->beacon, "sbi", "PUBLISH", (byte *)args->transmit,
args->length, beacon->interval);
return Qnil;
}

Expand Down Expand Up @@ -203,7 +191,7 @@ static VALUE rb_czmq_beacon_publish(VALUE obj, VALUE transmit)
static VALUE rb_czmq_nogvl_silence(void *ptr)
{
zmq_beacon_wrapper *beacon = ptr;
zbeacon_silence(beacon->beacon);
zstr_sendx(beacon->beacon, "SILENCE", NULL);
return Qnil;
}

Expand Down Expand Up @@ -233,7 +221,8 @@ static VALUE rb_czmq_nogvl_subscribe(void *ptr)
{
struct nogvl_beacon_subscribe_args *args = ptr;
zmq_beacon_wrapper *beacon = args->beacon;
zbeacon_subscribe(beacon->beacon, (byte *)args->filter ,args->length);
zsock_send(beacon->beacon, "sb", "SUBSCRIBE", (byte *)args->filter,
args->length);
return Qnil;
}

Expand Down Expand Up @@ -272,7 +261,7 @@ static VALUE rb_czmq_beacon_subscribe(VALUE obj, VALUE filter)
static VALUE rb_czmq_nogvl_unsubscribe(void *ptr)
{
zmq_beacon_wrapper *beacon = ptr;
zbeacon_unsubscribe(beacon->beacon);
zstr_sendx(beacon->beacon, "UNSUBSCRIBE", NULL);
return Qnil;
}

Expand All @@ -298,7 +287,7 @@ static VALUE rb_czmq_beacon_pipe(VALUE obj)
zmq_sock_wrapper *sock = NULL;
VALUE socket;
GetZmqBeacon(obj);
socket = rb_czmq_socket_alloc(Qnil, NULL, zbeacon_socket(beacon->beacon));
socket = rb_czmq_socket_alloc(Qnil, NULL, zsock_resolve(beacon->beacon));
GetZmqSocket(socket);
sock->state = ZMQ_SOCKET_BOUND;
return socket;
Expand Down
5 changes: 4 additions & 1 deletion ext/rbczmq/beacon.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
#define RBCZMQ_BEACON_H

typedef struct {
zbeacon_t *beacon;
zactor_t *beacon;
char *hostname;
int interval;
int port;
} zmq_beacon_wrapper;

#define ZmqAssertBeacon(obj) ZmqAssertType(obj, rb_cZmqBeacon, "ZMQ::Beacon")
Expand Down
12 changes: 7 additions & 5 deletions ext/rbczmq/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def check_heads heads = [], fatal = false

when /linux/
CZMQ_CFLAGS << "-fPIC"
CONFIG['LDSHARED'] = "$(CXX) -shared -lstdc++ -fPIC"

else
# on Unix we need a g++ link, not gcc.
Expand All @@ -105,7 +106,7 @@ def check_heads heads = [], fatal = false
lib = libs_path + "libsodium.#{LIBEXT}"
Dir.chdir libsodium_path do
sys "./autogen.sh", "libsodium autogen failed!" unless File.exist?(libsodium_path + 'configure')
sys "./configure --prefix=#{dst_path} --without-documentation --enable-shared",
sys "./configure CFLAGS='#{CZMQ_CFLAGS.join(" ")}' CXXFLAGS='#{CZMQ_CFLAGS.join(" ")}' --prefix=#{dst_path} --without-documentation --disable-shared --enable-static --disable-pie",
"libsodium configure failed" unless File.exist?(libsodium_path + 'Makefile')
sys "make && make install", "libsodium compile error!"
end
Expand All @@ -118,7 +119,7 @@ def check_heads heads = [], fatal = false
lib = libs_path + "libzmq.#{LIBEXT}"
Dir.chdir zmq_path do
sys "./autogen.sh", "ZeroMQ autogen failed!" unless File.exist?(zmq_path + 'configure')
sys "./configure --prefix=#{dst_path} --without-documentation --enable-shared",
sys "./configure CFLAGS='#{CZMQ_CFLAGS.join(" ")}' CXXFLAGS='#{CZMQ_CFLAGS.join(" ")}' --prefix=#{dst_path} --without-documentation --disable-shared --enable-static --with-libsodium=#{dst_path}",
"ZeroMQ configure failed" unless File.exist?(zmq_path + 'Makefile')
sys "make && make install", "ZeroMQ compile error!"
end
Expand All @@ -131,7 +132,7 @@ def check_heads heads = [], fatal = false
lib = libs_path + "libczmq.#{LIBEXT}"
Dir.chdir czmq_path do
sys "./autogen.sh", "CZMQ autogen failed!" unless File.exist?(czmq_path + 'configure')
sys "./configure LDFLAGS=-L#{libs_path} CFLAGS='#{CZMQ_CFLAGS.join(" ")}' --prefix=#{dst_path} --with-libzmq=#{dst_path} --disable-shared",
sys "./configure LDFLAGS='-L#{libs_path} -lm' CFLAGS='#{CZMQ_CFLAGS.join(" ")}' --prefix=#{dst_path} --disable-shared --enable-static --with-libsodium=#{dst_path}",
"CZMQ configure error!" unless File.exist?(czmq_path + 'Makefile')
sys "make all && make install", "CZMQ compile error!"
end
Expand All @@ -143,7 +144,7 @@ def check_heads heads = [], fatal = false
have_func('rb_thread_blocking_region')
have_func('rb_thread_call_without_gvl')

$INCFLAGS << " -I#{libsodium_include_path}" if find_header("sodidum.h", libsodium_include_path)
$INCFLAGS << " -I#{libsodium_include_path}" if find_header("sodium.h", libsodium_include_path)
$INCFLAGS << " -I#{zmq_include_path}" if find_header("zmq.h", zmq_include_path)
$INCFLAGS << " -I#{czmq_include_path}" if find_header("czmq.h", czmq_include_path)

Expand All @@ -154,13 +155,14 @@ def check_heads heads = [], fatal = false
CONFIG['LDSHARED'] = "#{CONFIG['LDSHARED']} -Wl,-rpath=#{libs_path.to_s}"
end

fail "Error compiling and linking libsodium" unless have_library("sodium")
fail "Error compiling and linking libzmq" unless have_library("zmq")
fail "Error compiling and linking libczmq" unless have_library("czmq")

$defs << "-pedantic"

$CFLAGS << ' -Wall -funroll-loops'
$CFLAGS << ' -Wextra -O0 -ggdb3' if ENV['DEBUG']
$LDFLAGS << " -Wl,-rpath,ext/rbczmq/dst/lib/"
$LDFLAGS << " -Wl,-rpath,'$$ORIGIN/dst/lib/'"

create_makefile('rbczmq_ext')
34 changes: 34 additions & 0 deletions ext/rbczmq/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -1737,6 +1737,39 @@ static VALUE rb_czmq_socket_opt_last_endpoint(VALUE obj)
return result;
}

/*
* call-seq:
* sock.stream_notify = false => nil
*
* Sets the socket stream_notify value.
*
* === Examples
* ctx = ZMQ::Context.new
* sock = ctx.socket(:STREAM)
* sock.stream_notify = false => nil
*
*/

static VALUE rb_czmq_socket_set_opt_stream_notify(VALUE obj, VALUE value)
{
int rc, optval;
zmq_sock_wrapper *sock = NULL;

GetZmqSocket(obj);
ZmqSockGuardCrossThread(sock);
CheckBoolean(value);
optval = (value == Qtrue) ? 1 : 0;

rc = zmq_setsockopt(sock->socket, ZMQ_STREAM_NOTIFY, &optval, sizeof(optval));
ZmqAssert(rc);

if (sock->verbose)
zclock_log ("I: %s socket %p: set option \"STREAM_NOTIFY\" %d",
zsocket_type_str(sock->socket), (void *)obj, optval);

return Qnil;
}

/*
* :nodoc:
* Receives a monitoring event message while the GIL is released.
Expand Down Expand Up @@ -1974,4 +2007,5 @@ void _init_rb_czmq_socket()
rb_define_method(rb_cZmqSocket, "sndtimeo=", rb_czmq_socket_set_opt_sndtimeo, 1);
rb_define_method(rb_cZmqSocket, "monitor", rb_czmq_socket_monitor, -1);
rb_define_method(rb_cZmqSocket, "last_endpoint", rb_czmq_socket_opt_last_endpoint, 0);
rb_define_method(rb_cZmqStreamSocket, "stream_notify=", rb_czmq_socket_set_opt_stream_notify, 1);
}
7 changes: 7 additions & 0 deletions ext/rbczmq/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,11 @@ extern VALUE intern_on_disconnected;
void _init_rb_czmq_socket();
VALUE rb_czmq_nogvl_zsocket_destroy(void *ptr);

#if (ZMQ_VERSION_MAJOR == 4 && ZMQ_VERSION_MINOR >= 1)
typedef struct {
uint16_t event; // id of the event as bitfield
int32_t value; // value is either error code, fd or reconnect interval
} zmq_event_t;
#endif

#endif
2 changes: 1 addition & 1 deletion ext/zeromq
Submodule zeromq updated 521 files
2 changes: 1 addition & 1 deletion rbczmq.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ Gem::Specification.new do |s|
end
end
end
end
end
Loading

0 comments on commit d782930

Please sign in to comment.