Skip to content

Commit 44dd03d

Browse files
authored
Merge pull request #21 from Asmod4n/master
Enable building libzmq again
2 parents fdbd525 + 6abebd8 commit 44dd03d

10 files changed

+100
-102
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "deps/libzmq"]
2+
path = deps/libzmq
3+
url = https://github.com/zeromq/libzmq

.travis.yml

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
dist: focal
2+
env:
3+
- BUILD_LIBZMQ=1
24
addons:
35
apt:
46
packages:

Rakefile

+5
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,9 @@ task :test => :mruby do
99
sh "cd mruby && MRUBY_CONFIG=#{MRUBY_CONFIG} rake all test"
1010
end
1111

12+
desc "cleanup"
13+
task :clean do
14+
sh "cd mruby && MRUBY_CONFIG=#{MRUBY_CONFIG} rake deep_clean"
15+
end
16+
1217
task :default => :test

build_config.rb

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
MRuby::Build.new do |conf|
22
toolchain :gcc
33
enable_debug
4-
conf.enable_sanitizer "address,undefined,leak"
5-
conf.cc.flags << '-fno-omit-frame-pointer' << '-g' << '-ggdb'
4+
conf.enable_debug
5+
conf.enable_sanitizer "address,undefined"
6+
conf.cc.flags << '-fno-omit-frame-pointer'
67
conf.enable_test
78
conf.gembox 'full-core'
89
conf.gem File.expand_path(File.dirname(__FILE__))

build_config.rb.lock

-27
This file was deleted.

deps/libzmq

Submodule libzmq added at 416b7ae

mrbgem.rake

+37-12
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,27 @@ MRuby::Gem::Specification.new('mruby-zmq') do |spec|
1616
spec.add_dependency 'mruby-metaprog'
1717
spec.add_test_dependency 'mruby-sleep'
1818

19+
def build_libzmq(spec, build)
20+
unless File.exists?("#{spec.build_dir}/build/lib/libzmq.a")
21+
warn "mruby-zmq: cannot find libzmq, building it"
22+
sh "mkdir -p #{spec.build_dir}/build && cd #{spec.build_dir}/build && cmake -DCMAKE_INSTALL_PREFIX=\"#{spec.build_dir}\" -DENABLE_DRAFTS=ON #{spec.dir}/deps/libzmq/ && cmake --build . -j4 --target libzmq-static"
23+
end
24+
spec.linker.flags_before_libraries << "\"#{spec.build_dir}/build/lib/libzmq.a\""
25+
`pkg-config --cflags \"#{spec.build_dir}/build/libzmq.pc\"`.split("\s").each do |cflag|
26+
spec.cxx.flags << cflag
27+
spec.cc.flags << cflag
28+
end
29+
`pkg-config --static --libs \"#{spec.build_dir}/build/libzmq.pc\"`.split("\s").each do |lib|
30+
spec.linker.flags_before_libraries << lib
31+
end
32+
spec.cc.include_paths << "#{spec.dir}/deps/libzmq/include"
33+
spec.cxx.include_paths << "#{spec.dir}/deps/libzmq/include"
34+
build.cc.include_paths << "#{spec.dir}/deps/libzmq/include"
35+
build.cxx.include_paths << "#{spec.dir}/deps/libzmq/include"
36+
spec.cxx.defines << 'ZMQ_BUILD_DRAFT_API=1'
37+
spec.cc.defines << 'ZMQ_BUILD_DRAFT_API=1'
38+
end
39+
1940
if spec.cc.search_header_path 'threads.h'
2041
spec.cc.defines << 'HAVE_THREADS_H'
2142
end
@@ -25,18 +46,22 @@ MRuby::Gem::Specification.new('mruby-zmq') do |spec|
2546
if spec.build.toolchains.include? 'visualcpp'
2647
spec.linker.libraries << 'libzmq'
2748
else
28-
`pkg-config --cflags libzmq 2>/dev/null`.split("\s").each do |cflag|
29-
spec.cxx.flags << cflag
30-
spec.cc.flags << cflag
31-
end
32-
exitstatus = $?.exitstatus
33-
`pkg-config --libs libzmq 2>/dev/null`.split("\s").each do |lib|
34-
spec.linker.flags_before_libraries << lib
35-
end
36-
exitstatus += $?.exitstatus
37-
unless exitstatus == 0
38-
raise "install libzmq(-dev) before continuing"
49+
if ENV['BUILD_LIBZMQ']
50+
build_libzmq(spec, build)
51+
else
52+
`pkg-config --cflags libzmq 2>/dev/null`.split("\s").each do |cflag|
53+
spec.cxx.flags << cflag
54+
spec.cc.flags << cflag
55+
end
56+
exitstatus = $?.exitstatus
57+
`pkg-config --libs libzmq 2>/dev/null`.split("\s").each do |lib|
58+
spec.linker.flags_before_libraries << lib
59+
end
60+
exitstatus += $?.exitstatus
61+
unless exitstatus == 0
62+
build_libzmq(spec, build)
63+
end
3964
end
40-
spec.linker.flags_before_libraries << '-pthread' << '-lpthread'
65+
spec.linker.flags_before_libraries << '-pthread'
4166
end
4267
end

src/mrb_libzmq.c

+44-55
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,37 @@ mrb_zmq_z85_encode(mrb_state *mrb, mrb_value self)
623623
return dest;
624624
}
625625

626+
static void
627+
mrb_zmq_thread_fn_cb(mrb_state *mrb, const mrb_value mrb_zmq_thread_data_)
628+
{
629+
mrb_zmq_thread_data_t *mrb_zmq_thread_data = (mrb_zmq_thread_data_t *) mrb_cptr(mrb_zmq_thread_data_);
630+
631+
struct RClass* zmq_mod = mrb_module_get(mrb, "ZMQ");
632+
mrb_value pipe_val = mrb_obj_value(mrb_obj_alloc(mrb, MRB_TT_DATA, mrb_class_get_under(mrb, zmq_mod, "Pair")));
633+
mrb_data_init(pipe_val, mrb_zmq_thread_data->backend, &mrb_zmq_socket_type);
634+
mrb_value timeo = mrb_int_value(mrb, 120000);
635+
mrb_funcall(mrb, pipe_val, "sndtimeo=", 1, timeo);
636+
mrb_funcall(mrb, pipe_val, "rcvtimeo=", 1, timeo);
637+
638+
mrb_value argv = mrb_msgpack_unpack(mrb, mrb_zmq_thread_data->argv_str);
639+
mrb_value block = mrb_msgpack_unpack(mrb, mrb_zmq_thread_data->block_str);
640+
if (mrb_type(mrb_ary_ref(mrb, argv, 0)) == MRB_TT_CLASS) {
641+
mrb_value bg_class = mrb_ary_shift(mrb, argv);
642+
enum mrb_vtype ttype = MRB_INSTANCE_TT(mrb_class_ptr(bg_class));
643+
if (ttype == 0) ttype = MRB_TT_OBJECT;
644+
mrb_zmq_thread_data->thread_fn = mrb_obj_value(mrb_obj_alloc(mrb, ttype, mrb_class_ptr(bg_class)));
645+
} else {
646+
mrb_zmq_thread_data->thread_fn = mrb_obj_value(mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb_class_get_under(mrb, mrb_class_get_under(mrb, zmq_mod, "Thread"), "Thread_fn")));
647+
}
648+
mrb_iv_set(mrb, mrb_zmq_thread_data->thread_fn, mrb_intern_lit(mrb, "@pipe"), pipe_val);
649+
mrb_funcall_with_block(mrb, mrb_zmq_thread_data->thread_fn, mrb_intern_lit(mrb, "initialize"), RARRAY_LEN(argv), RARRAY_PTR(argv), block);
650+
int success = TRUE;
651+
int rc = zmq_send(mrb_zmq_thread_data->backend, &success, sizeof(success), 0);
652+
if (unlikely(rc == -1)) {
653+
mrb_zmq_handle_error(mrb, "zmq_send");
654+
}
655+
}
656+
626657
static int
627658
mrb_zmq_thread_fn(void *mrb_zmq_thread_data_)
628659
{
@@ -634,49 +665,14 @@ mrb_zmq_thread_fn(void *mrb_zmq_thread_data_)
634665
mrb_state *mrb = mrb_open_allocf(mrb_zmq_thread_data->mrb_parent->allocf, mrb_zmq_thread_data->mrb_parent->allocf_ud);
635666
if (likely(mrb)) {
636667
mrb_zmq_thread_data->backend_ctx = MRB_LIBZMQ_CONTEXT(mrb);
637-
mrb_value thread_fn = mrb_nil_value();
638-
639-
struct mrb_jmpbuf* prev_jmp = mrb->jmp;
640-
struct mrb_jmpbuf c_jmp;
641-
642-
MRB_TRY(&c_jmp)
643-
{
644-
mrb->jmp = &c_jmp;
645-
struct RClass* zmq_mod = mrb_module_get(mrb, "ZMQ");
646-
mrb_value pipe_val = mrb_obj_value(mrb_obj_alloc(mrb, MRB_TT_DATA, mrb_class_get_under(mrb, zmq_mod, "Pair")));
647-
mrb_data_init(pipe_val, mrb_zmq_thread_data->backend, &mrb_zmq_socket_type);
648-
mrb_value timeo = mrb_int_value(mrb, 120000);
649-
mrb_funcall(mrb, pipe_val, "sndtimeo=", 1, timeo);
650-
mrb_funcall(mrb, pipe_val, "rcvtimeo=", 1, timeo);
651-
652-
mrb_value argv = mrb_msgpack_unpack(mrb, mrb_zmq_thread_data->argv_str);
653-
mrb_value block = mrb_msgpack_unpack(mrb, mrb_zmq_thread_data->block_str);
654-
if (mrb_type(mrb_ary_ref(mrb, argv, 0)) == MRB_TT_CLASS) {
655-
mrb_value bg_class = mrb_ary_shift(mrb, argv);
656-
enum mrb_vtype ttype = MRB_INSTANCE_TT(mrb_class_ptr(bg_class));
657-
if (ttype == 0) ttype = MRB_TT_OBJECT;
658-
thread_fn = mrb_obj_value(mrb_obj_alloc(mrb, ttype, mrb_class_ptr(bg_class)));
659-
} else {
660-
thread_fn = mrb_obj_value(mrb_obj_alloc(mrb, MRB_TT_OBJECT, mrb_class_get_under(mrb, mrb_class_get_under(mrb, zmq_mod, "Thread"), "Thread_fn")));
661-
}
662-
mrb_iv_set(mrb, thread_fn, mrb_intern_lit(mrb, "@pipe"), pipe_val);
663-
mrb_funcall_with_block(mrb, thread_fn, mrb_intern_lit(mrb, "initialize"), RARRAY_LEN(argv), RARRAY_PTR(argv), block);
664-
success = TRUE;
665-
666-
rc = zmq_send(mrb_zmq_thread_data->backend, &success, sizeof(success), 0);
667-
if (unlikely(rc == -1)) {
668-
mrb_zmq_handle_error(mrb, "zmq_send");
669-
}
670-
mrb->jmp = prev_jmp;
671-
}
672-
MRB_CATCH(&c_jmp)
673-
{
674-
mrb->jmp = prev_jmp;
675-
success = FALSE;
676-
mrb_value old_exc = mrb_obj_value(mrb->exc);
677-
mrb->exc = NULL;
678-
if (mrb_test(old_exc) && mrb_exception_p(old_exc)) {
679-
mrb_value exc = mrb_msgpack_pack(mrb, old_exc);
668+
mrb_zmq_thread_data->thread_fn = mrb_nil_value();
669+
670+
mrb_bool error = FALSE;
671+
mrb_value exc = mrb_protect(mrb, mrb_zmq_thread_fn_cb, mrb_cptr_value(mrb, mrb_zmq_thread_data), &error);
672+
success = !error;
673+
if (unlikely(error)) {
674+
if (mrb_test(exc) && mrb_exception_p(exc)) {
675+
exc = mrb_msgpack_pack(mrb, exc);
680676
if (mrb_string_p(exc)) {
681677
zmq_send(mrb_zmq_thread_data->backend, &success, sizeof(success), ZMQ_SNDMORE);
682678
zmq_send(mrb_zmq_thread_data->backend, RSTRING_PTR(exc), RSTRING_LEN(exc), 0);
@@ -688,17 +684,18 @@ mrb_zmq_thread_fn(void *mrb_zmq_thread_data_)
688684
}
689685
zmq_close(mrb_zmq_thread_data->backend);
690686
}
691-
MRB_END_EXC(&c_jmp);
692687

693688
mrb_gc_arena_restore(mrb, 0);
694689
if (likely(success)) {
695-
mrb_gc_protect(mrb, thread_fn);
696-
mrb_funcall(mrb, thread_fn, "run", 0);
690+
mrb_gc_register(mrb, mrb_zmq_thread_data->thread_fn);
691+
mrb_funcall(mrb, mrb_zmq_thread_data->thread_fn, "run", 0);
697692
}
693+
698694
if (mrb->exc && !mrb_obj_is_kind_of(mrb, mrb_obj_value(mrb->exc), E_ETERM_ERROR)) {
699695
success = FALSE;
700696
mrb_print_error(mrb);
701697
}
698+
702699
mrb_close(mrb);
703700
} else {
704701
zmq_send(mrb_zmq_thread_data->backend, &success, sizeof(success), 0);
@@ -725,8 +722,6 @@ mrb_zmq_threadstart(mrb_state *mrb, mrb_value thread_class)
725722
mrb_zmq_thread_data_t *mrb_zmq_thread_data = (mrb_zmq_thread_data_t *) mrb_realloc(mrb, DATA_PTR(self), sizeof(*mrb_zmq_thread_data));
726723
memset(mrb_zmq_thread_data, 0, sizeof(*mrb_zmq_thread_data));
727724
mrb_data_init(self, mrb_zmq_thread_data, &mrb_zmq_thread_type);
728-
mrb_value threads = mrb_iv_get(mrb, mrb_obj_value(mrb_class_get_under(mrb, mrb_module_get(mrb, "ZMQ"), "Thread")), mrb_intern_lit(mrb, "threads"));
729-
mrb_hash_set(mrb, threads, mrb_int_value(mrb, (intptr_t) mrb_zmq_thread_data), self);
730725
mrb_zmq_thread_data->mrb_parent = mrb;
731726
mrb_zmq_thread_data->argv_str = mrb_msgpack_pack_argv(mrb, argv, argv_len);
732727
mrb_zmq_thread_data->block_str = mrb_msgpack_pack(mrb, block);
@@ -793,8 +788,6 @@ mrb_zmq_threadclose(mrb_state *mrb, mrb_value self)
793788
mrb_free(mrb, mrb_zmq_thread_data);
794789
mrb_data_init(thread_val, NULL, NULL);
795790
mrb_iv_remove(mrb, thread_val, mrb_intern_lit(mrb, "@pipe"));
796-
mrb_value threads = mrb_iv_get(mrb, mrb_obj_value(mrb_class_get_under(mrb, mrb_module_get(mrb, "ZMQ"), "Thread")), mrb_intern_lit(mrb, "threads"));
797-
mrb_hash_delete_key(mrb, threads, mrb_int_value(mrb, (intptr_t) mrb_zmq_thread_data));
798791
return mrb_bool_value(success);
799792
}
800793

@@ -1468,8 +1461,6 @@ mrb_mruby_zmq_gem_init(mrb_state* mrb)
14681461
MRB_SET_INSTANCE_TT(zmq_thread_class, MRB_TT_DATA);
14691462
mrb_define_class_method(mrb, zmq_thread_class, "new", mrb_zmq_threadstart, MRB_ARGS_ANY());
14701463

1471-
mrb_iv_set(mrb, mrb_obj_value(zmq_thread_class), mrb_intern_lit(mrb, "threads"), mrb_hash_new(mrb));
1472-
14731464
struct RClass *zmq_poller_class = mrb_define_class_under(mrb, zmq_mod, "Poller", mrb->object_class);
14741465
MRB_SET_INSTANCE_TT(zmq_poller_class, MRB_TT_DATA);
14751466
mrb_define_const(mrb, zmq_poller_class, "In", mrb_int_value(mrb, ZMQ_POLLIN));
@@ -1543,10 +1534,8 @@ mrb_mruby_zmq_gem_init(mrb_state* mrb)
15431534
void
15441535
mrb_mruby_zmq_gem_final(mrb_state* mrb)
15451536
{
1546-
struct RClass *zmq_mod = mrb_module_get(mrb, "ZMQ");
1547-
mrb_objspace_each_objects(mrb, mrb_zmq_thread_close_gem_final, mrb_class_get_under(mrb, zmq_mod, "Thread"));
15481537
void *context = MRB_LIBZMQ_CONTEXT(mrb);
15491538
zmq_ctx_shutdown(context);
1550-
mrb_objspace_each_objects(mrb, mrb_zmq_zmq_close_gem_final, mrb_class_get_under(mrb, zmq_mod, "Socket"));
1539+
mrb_objspace_each_objects(mrb, mrb_zmq_zmq_close_gem_final, mrb_class_get_under(mrb, mrb_module_get(mrb, "ZMQ"), "Socket"));
15511540
zmq_ctx_term(context);
15521541
}

src/mrb_libzmq.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ typedef struct {
106106
mrb_state *mrb_parent;
107107
mrb_value argv_str;
108108
mrb_value block_str;
109+
mrb_value thread_fn;
109110
const char *endpoint;
110111
void *frontend;
111112
void *backend;
@@ -129,8 +130,6 @@ mrb_zmq_gc_threadclose(mrb_state *mrb, void *mrb_zmq_thread_data_)
129130
if (likely(mrb_zmq_thread_data->thread)) {
130131
thrd_join(mrb_zmq_thread_data->thread, NULL);
131132
}
132-
mrb_value threads = mrb_iv_get(mrb, mrb_obj_value(mrb_class_get_under(mrb, mrb_module_get(mrb, "ZMQ"), "Thread")), mrb_intern_lit(mrb, "threads"));
133-
mrb_hash_delete_key(mrb, threads, mrb_int_value(mrb, (intptr_t) mrb_zmq_thread_data_));
134133
mrb_free(mrb, mrb_zmq_thread_data_);
135134
}
136135
}

test/zmq.rb

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
publisher = ZMQ::Pub.new(ZMQ.ipv6? ? "tcp://[::1]:*" : "tcp://127.0.0.1:*")
1111
publisher.sndtimeo = 500
1212
subscriber = ZMQ::Sub.new(publisher.last_endpoint, "hallo")
13-
sleep 2
13+
sleep 1
1414
publisher.send("hallo ballo")
1515
subscriber.rcvtimeo = 500
1616
msg = subscriber.recv
@@ -74,9 +74,9 @@
7474
msg = ZMQ::Msg.new("hallo")
7575
msg.group = "test_zmq"
7676
msg.send(radio)
77-
msg = dish.recv
78-
assert_equal("hallo", msg.to_str)
79-
assert_equal("test_zmq", msg.group)
77+
msg2 = dish.recv
78+
assert_equal("hallo", msg2.to_str)
79+
assert_equal("test_zmq", msg2.group)
8080
end
8181
end
8282

0 commit comments

Comments
 (0)