diff --git a/lib/process_shared/condition_variable.rb b/lib/process_shared/condition_variable.rb index 0fd42b4..bf4d17c 100644 --- a/lib/process_shared/condition_variable.rb +++ b/lib/process_shared/condition_variable.rb @@ -16,7 +16,9 @@ module ProcessShared end def signal - @sem.post + @internal.synchronize do + @sem.post unless @waiting.read_int.zero? + end end def wait(mutex, timeout = nil) diff --git a/lib/process_shared/shared_memory_io.rb b/lib/process_shared/shared_memory_io.rb index a21a8a0..dee31fb 100644 --- a/lib/process_shared/shared_memory_io.rb +++ b/lib/process_shared/shared_memory_io.rb @@ -198,6 +198,7 @@ module ProcessShared def read(length = nil, buffer = nil) length ||= (mem.size - pos) buffer ||= '' + buffer.force_encoding('ASCII-8BIT') unless RUBY_VERSION.start_with?('1.8') actual_length = [(mem.size - pos), length].min actual_length.times do diff --git a/spec/process_shared/condition_variable_spec.rb b/spec/process_shared/condition_variable_spec.rb index 7ffcaba..8631503 100644 --- a/spec/process_shared/condition_variable_spec.rb +++ b/spec/process_shared/condition_variable_spec.rb @@ -63,5 +63,19 @@ module ProcessShared (Time.now.to_f - start).must be_gte(0.1) } end + + it 'correctly handles #signal when no waiters' do + mutex = Mutex.new + cond = ConditionVariable.new + + # fix for bug: #wait not waiting after unmatched call to #signal + cond.signal + + mutex.synchronize { + start = Time.now.to_f + cond.wait(mutex, 0.1) + (Time.now.to_f - start).must be_gte(0.1) + } + end end end diff --git a/spec/process_shared/shared_memory_io_spec.rb b/spec/process_shared/shared_memory_io_spec.rb new file mode 100644 index 0000000..2c31173 --- /dev/null +++ b/spec/process_shared/shared_memory_io_spec.rb @@ -0,0 +1,40 @@ +# encoding: UTF-8 +# ^^^ +# NOTE: This magic comment is necessary for the UTF-8 string literal below +# on Ruby 1.9.x +require 'spec_helper' +require 'process_shared' + +module ProcessShared + describe SharedMemoryIO do + + describe '#read' do + def binary(s) + (RUBY_VERSION == '1.8.7') ? s : s.force_encoding('ASCII-8BIT') + end + + def output_for(input) + mem = SharedMemory.new(16) + mem.put_bytes(0, input, 0, input.bytesize) + io = SharedMemoryIO.new(mem) + io.read(input.bytesize) + end + + it 'returns correct binary data for plain ASCII string' do + input = 'Hello' + output_for(input).must_equal binary(input) + end + + it 'returns correct binary data for UTF-8 string' do + input = 'Mária' + output_for(input).must_equal binary(input) + end + + it 'returns correct binary data for explicitly binary data' do + input = "\x00\xD1\x9B\x86\x00" + output_for(input).must_equal binary(input) + end + end + + end +end