(Re)loading the playlist uses the new mutex and
shm helpers and is hopefully a race-free implementation.
It works as follows:
The plm init function (parent, server context) reserves
a shared memory area (client data) as well as two unlocked
mutexes. The first mutex serializes access for racing clients
that want to replace the playlist. The second mutex serializes
the access between parent and child (com_lpl()).
com_lpl() loads the playlist from the client into a tmp buffer.
It then creates a shm area (client_shm) and copies that buffer
to the area. Further, another mutex (shm) is created. This
mutex is initially locked.
Next, it grabs the client lock and the server lock, and updates
client_data with the id of client_shm. Then the parent is
woken up (SIGUSR1) and the server lock is released. com_lpl()
finally goes to sleep by acquiring the shm lock.
In this situation, only the parent may run. It grabs the
server lock, reads client_data to attach client_shm and
reloads the playlist with data from client_shm. When ready,
the parent detaches client_shm, and drops the shm lock and
the server lock.
This wakes up com_lpl() which destroys client_shm, the
shm mutex and the tmp buffer.