Sunday, November 30, 2008

FreeBSD: sem_open bug

Recently I've been testing libdodo on FreeBSD 7.0
Any time sem_open was called I received 'bad system call' and abort signal from ksem_open routine.

sem_open is buggy in FreeBSD, man 3 sem_open:

BUGS
     This implementation places strict requirements on the value of name: it
     must begin with a slash (`/'), contain no other slash characters, and be
     less than 14 characters in length not including the terminating null
     character.
Anyway I was giving sem_open 14 bytes long key with leading '/' and it continued to fail.
Program received signal SIGSYS, Bad system call.
[Switching to Thread 0x28f01100 (LWP 100056)]
0x2891c84b in ksem_open () from /lib/libc.so.7
(gdb) bt
#0  0x2891c84b in ksem_open () from /lib/libc.so.7
#1  0x2891209c in sem_open () from /lib/libc.so.7
#2  0x28767386 in single (this=0x804b520, value=1, a_key=@0x804b4dc) at src/pcSyncProcessDataSingle.cc:58
#3  0x0804969c in __static_initialization_and_destruction_0 (__initialize_p=Variable "__initialize_p" is not available.
) at test.cc:24
#4  0x0804aaf5 in __do_global_ctors_aux ()
#5  0x080491ed in _init ()
#6  0x00000000 in ?? ()
#7  0x00000000 in ?? ()
#8  0xbfbfecbc in ?? ()
#9  0x080495a6 in _start ()
#10 0x00000001 in ?? ()
(gdb) up
#1  0x2891209c in sem_open () from /lib/libc.so.7
(gdb) 
#2  0x28767386 in single (this=0x804b520, value=1, a_key=@0x804b4dc) at src/pcSyncProcessDataSingle.cc:58
58  semaphore = sem_open(key.c_str(), O_CREAT, S_IWUSR, value);
(gdb) p key
$1 = {static npos = 4294967295, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x28f4a24c "/c5b80cc1e0"}}
(gdb) p value
$2 = 1
The bug is somewhere in the kernel. I should look for another implementation of semaphores in FreeBSD.

4 comments:

decke said...

I'm having the same problem on FreeBSD 7-STABLE with a different application. You can try to narrow that down by checking what value "errno" has.

Good luck.

Ni@m said...

It failed to return from sem_open. The signal was raised. Set a signal handler to catch this?

decke said...

I've digged a bit deeper and FreeBSD 7 supports SysV semaphores out of the box but POSIX semaphores are experimental and not part of the GENERIC kernel yet. You can enable POSIX semaphores by using "option P1003_1B_SEMAPHORES" in your kernel config (see /usr/src/sys/conf/NOTES) but that's a no-go if you want to create a port. My solution to the problem was to rewrite the code to SysV semaphores and luckily it wasn't that much code.

For clarification SysV semaphores are semget/semop/semctl and POSIX semaphores are sem_open/sem_close/sem_*

Ni@m said...

Yep, I know that POSIX semaphores are not enabled by default in FreeBSD 7.0. This is the problem for the application which could run in the environment which couldn't be changed just because one application that.
XSI semaphores work fine for me and I don't see significant performance changes.
I wonder why not to return errno=ENOSYS but to send SIGSYS.
It's worth to receive SIGSYS in all meanings.