h.b.furuseth@usit.uio.no wrote:
Reopening this.
This is worse with a database with is intended to be used by different users (A and B):
This is pretty much never a use case we would worry about. In most applications, a single userID creates and operates on the DB.
A opens the DB and creates the semaphores with e.g. mode 0660. B opens it, A closes, B closes - and fails sem_unlink() which only A and root can do.
Next, B (or C) fails mdb_env_open() because sem_unlink() fails again.
The work-around I can think of is a "multi-uid" mode which instead resets the semaphore with sem_post() if sem_getvalue() returns 0. I don't know how ugly that is considered to be. Could ask comp.programming.unix, or check what Berkeley DB does.
That would be OK in general. It still leaves the question of how to remove the semaphore if the DB is being destroyed. But it's probably not worth the trouble to worry about this so much. Those OSes should just get their act together and support the POSIX process-shared mutexes.
This mode should use mode 0666 for the semaphores (temporarily setting umask 0, yuck),
Definitely not. The caller specifies a mode; if they want 0666 they should configure it as such.
or it should not sem_unlink() since next user may create the semaphores with a group which gives the wrong users access.
Same as today where running slapadd with the wrong uid causes trouble for the following slapd. The answer is obvious: use the right uid when accessing the DB.
Other matters with the current implementation - I'll patch these:
mdb_env_excl_lock() need not retry getting a non-exclusive lock when closing. mdb_env_close() can pass *excl = -1 to tell it not to.
mdb_env_setup_locks() can sem_unlink both semaphores before doing anything else, so that reopening a database as root will clean up. Drop the error checks of sem_unlink (so both get called), instead use O_EXCL in sem_open(,O_CREAT,,). Unless I'm missing something, the error checks just work like an emulation of O_EXCL anyway.
The sem_unlink() and sem_open() sequence isn't ideal, certainly. I would prefer to just use the existing semaphore.
Another possibility is to just use SysV semaphores instead of POSIX semaphores. Then you can use the ipcs(1) command to manually cleanup. BerkeleyDB uses SysV shared memory when you specify a shared memory environment and it appears that SysV semaphore support is actually more widespread than POSIX semaphores.