Skip to content

Instantly share code, notes, and snippets.

@paddor
Created December 24, 2015 18:01
Show Gist options
  • Save paddor/3cb70f285552ba65a620 to your computer and use it in GitHub Desktop.
Save paddor/3cb70f285552ba65a620 to your computer and use it in GitHub Desktop.
#include "callback_bug.h"
#include <pthread.h>
#include <assert.h>
#include <stdlib.h>
typedef struct {
callback_fn *callback;
void *args; // Application arguments
} shim_t;
static void *
s_thread_shim (void *args)
{
assert (args);
shim_t *shim = (shim_t *) args;
char *name = (char *) shim->args;
printf("%s: calling callback ...\n", name);
shim->callback();
printf("%s: callback has returned.\n", name);
return NULL;
}
void
call_callback(callback_fn *callback, void *args)
{
shim_t *shim = (shim_t *) malloc (sizeof (shim_t));
if (!shim) {
printf("shim allocation failed\n");
return;
}
shim->callback = callback;
shim->args = args;
pthread_t thread;
pthread_create (&thread, NULL, s_thread_shim, shim);
pthread_detach (thread);
}
#ifndef __CALLBACK_BUG_H_INCLUDED__
#define __CALLBACK_BUG_H_INCLUDED__
#include <stdio.h>
typedef void (callback_fn) (void);
void
call_callback(callback_fn *callback, void *args);
#endif
require 'ffi'
module CallbackBug
extend ::FFI::Library
lib_name = 'libcallback_bug'
ffi_lib "#{lib_name}.#{::FFI::Platform::LIBSUFFIX}"
attach_function :call_callback, [:pointer, :pointer], :void, blocking: true
end
class Foo
def initialize(name)
name_ptr = FFI::MemoryPointer.from_string(name)
@callback = FFI::Function.new(:void, [], blocking: true) do
yield
end
CallbackBug.call_callback(@callback, name_ptr)
end
end
f1 = Foo.new("f1") do
begin
puts "f1: indefinitely running block, e.g. actor handler"
sleep
ensure
puts "f1: block is being GC'd"
end
end
ObjectSpace.define_finalizer(f1) do
puts "f1 is being GC'd"
end
Foo.new("f2") do
begin
puts "f2"
ensure
puts "f2: block is being GC'd"
end
end
sleep 0.5
f1 = nil
GC.start
sleep 1
puts "__END__"
# What this script shows is that the callback for f1 never returns, so the
# mesage "f1: callback has returned." is not printed.
libcallback_bug.dylib: callback_bug.h callback_bug.c
clang -dynamiclib -std=gnu99 callback_bug.c -o $@
$ ruby callback_bug.rb
f1: calling callback ...
f2: calling callback ...
f1: indefinitely running block, e.g. actor handler
f2
f2: block is being GC'd
f2: callback has returned.
__END__
f1: block is being GC'd
f1 is being GC'd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment