More Ruby Gymnastics

Last night, I got the SemaphoreManager working properly. It took over an hour and a half to do it properly b/c of inadequate documentation and examples in the “pickaxe” book and on the Web. First, the problem.

SemaphoreManager is a Ruby-level API that uses my sysv_semaphore extension for the low-level stuff. On error, sysv_semaphore was using rb_raise() to raise a SystemCallError exception on error. On the face of it, this isn’t a bug, except that SemaphoreManager needed to know which error it was.

SemaphoreManager uses a Settings file to store semaphore information by name. This allows other Ruby modules/objects to access semaphores by type instead of by hard-coded key strings. Eventually, however, this all needs to be converted to integers and sent down to the sysv_semaphore code.

The pseudo-code looks like the following:
SemaphoreManager::acquire_semaphore(key, channel, num_channels = 0)
 begin
  id = SysvSemaphore.get(key)
  SysvSemaphore.acquire(id, channel)
 rescue Errno::ENOENT => e
  raise if num_channels == 0
  id = SysvSemaphore.create(key, num_channels)
  SysvSemaphore.reset(id)
  retry
 end
end

The problem is that, initially, I was trying to rescue SystemCallError. Unfortunately, by using rb_raise within the sysv_semaphore extension, the errno method wasn’t returning the error number of the failure. After reading through the docs, I saw that Errno was the exception to rescue, but there were no examples on how to raise this exception.

Finally, after scouring the Web, I found the rb_sys_fail() call in the pickaxe book. Low and behold, this was the call that creates and raises the appropriate Errno exception. The book itself was silent and there were no examples on the Web.

With that out of the way, it is now time to build the Javascript XmlCGI response parser. Web services, here we come.

Comments are closed.