Hi, At Wed, 16 May 2007 15:40:08 +0900, Pete wrote in [ruby-talk:251765]: > void callback_from_handler(....){ > if (!rb_block_given_p() || !receiving || ...) return; // do nothing unless active > VALUE bev = rb_class_new_instance(... cBMidiEvent); // event data copied to new obj > VALUE res = rb_yield(bev); // pass event to code block > if (RTEST(res)) { // not nil or false -- used as termination signal > receiving = false; > release_sem(); // tell 'do_each' to wake up > } > } From where is this function called? Unless it's called as a ruby method, you can't use rb_yield() in it. You might assume the block to bmidi_each() is accessible, it is never guaranteed at all. > VALUE bmidi_ensure(VALUE self) { > if (receiving) { // only if not terminated normally (details omitted...) > release_sem(); > } > receiving = false; > return self; > } > > VALUE bmidi_doeach(VALUE self) { > receiving = true; > acquire_sem(); // sleep until woken (timeout etc omitted) > return self; > } Since bmidi_ensure() won't get called until bmidi_doeach() ends, the latter seems to success to acquire the semaphore only when the callback released it. At that time, the callback sets receiving to false before the release, so the bmidi_ensure() leaves the semaphore locked which acquired by bmidi_doeach(), I guess. In short, the sequence is wrong. Anyway, you need to call rb_yield() in bmidi_each(). void callback_from_handler(....) { VALUE bev = rb_class_new_instance(... cBMidiEvent); acquire_sem(); received_bmidievent = bev; // pass event to 'each' release_sem(); // tell 'each' to wake up } VALUE bmidi_each(VALUE self) { VALUE res; rb_need_block(); do { acquire_sem(); VALUE bev = received_bmidievent; release_sem(); res = rb_yield(bev); // pass event to code block } while (RTEST(res)); return self; } -- Nobu Nakada