Skip to content

Commit c932d5b

Browse files
committed
Avoid struct-by-value argument for rb_thread_wait_for()
* struct by value arguments are not well supported from NFI to Sulong, sometimes it works by chance due to how it is compiled to bitcode. * This is the only struct-by-value argument in the C API subset we implement.
1 parent ac0ca1a commit c932d5b

File tree

3 files changed

+18
-3
lines changed

3 files changed

+18
-3
lines changed

lib/cext/include/ruby/internal/intern/thread.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,14 @@ VALUE rb_thread_create(VALUE (*f)(void *g), void *g);
196196
* @param[in] time Duration.
197197
* @exception rb_eInterrupt Interrupted.
198198
*/
199+
#ifdef TRUFFLERUBY
200+
void rb_tr_thread_wait_for(struct timeval* time);
201+
static inline void rb_thread_wait_for(struct timeval time) {
202+
rb_tr_thread_wait_for(&time);
203+
}
204+
#else
199205
void rb_thread_wait_for(struct timeval time);
206+
#endif
200207

201208
/**
202209
* Obtains the "current" thread.

src/main/c/cext/thread.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ VALUE rb_thread_local_aset(VALUE thread, ID id, VALUE val) {
2929
return RUBY_INVOKE(thread, "[]=", ID2SYM(id), val);
3030
}
3131

32-
void rb_thread_wait_for(struct timeval time) {
33-
double seconds = (double)time.tv_sec + (double)time.tv_usec/1000000;
32+
void rb_tr_thread_wait_for(struct timeval* time) {
33+
double seconds = (double)time->tv_sec + (double)time->tv_usec/1000000;
3434
polyglot_invoke(rb_tr_unwrap(rb_mKernel), "sleep", seconds);
3535
}
3636

tool/generate-cext-trampoline.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,17 @@
5555
functions.concat found_functions
5656
end
5757

58+
def struct_by_value?(type)
59+
type =~ /\bstruct\b/ and !type.include?('*')
60+
end
61+
5862
functions.each do |declaration, return_type, function_name, argument_types|
5963
raise declaration if /\bstatic\b/ =~ declaration
6064
raise declaration if function_name.start_with?('rb_tr_init') and function_name != 'rb_tr_init_exception'
6165
if declaration.include? "\n"
6266
abort "This declaration includes newlines but should not:\n#{declaration}\n\n"
6367
end
64-
if return_type =~ /\bstruct\s/ and !return_type.include?('*')
68+
if struct_by_value? return_type
6569
abort "Returning a struct by value from Sulong to NFI is not supported for:\n#{declaration}"
6670
end
6771
end
@@ -188,6 +192,10 @@
188192
argument_names = argument_types.delete_prefix('(').delete_suffix(')')
189193
argument_names = argument_names.scan(/(?:^|,)\s*(#{argument_regexp})\s*(?=,|$)/o)
190194
argument_names = argument_names.map { |full_arg, name1, name2|
195+
if struct_by_value? full_arg
196+
abort "struct by value argument not well supported from NFI to Sulong: #{full_arg}\n#{declaration}"
197+
end
198+
191199
if full_arg == "void"
192200
""
193201
elsif full_arg == "..."

0 commit comments

Comments
 (0)