What is a good portable way to implement a global signalable event in a POSIX environment

StackOverflow https://stackoverflow.com/questions/8741774

  •  14-04-2021
  •  | 
  •  

Question

The usage case is that one application generates an event and sends out a signal that any application that cares to listen for it will get. E.g. an application updates the contents of a file and signals this. On Linux this could be done by the waiters calling inotify on the file. One portable way would be for listeners to register with a well-known server, but I would prefer something simpler if possible. As portable as possible ideally means using only POSIX features which are also widely available.

Was it helpful?

Solution

Option using lock files

You can do this by locking a file.

Signal emitter initial setup:

  • Create a file with a well-known name and lock it for writing (fcntl(F_SETLK) with F_WRLCK or flock(LOCK_EX)`).

Signal receiver procedure:

  • Open the file using the well-known filename and try to obtain a read lock on it (fcntl(F_SETLK) with F_RDLCK or flock(LOCK_SH)).
  • Receiver blocks because the emitter is holding a conflicting write lock.

Signal emission:

  • Signal emitter creates a new temporary file
  • Signal emitter obtains a write lock on the new temporary file
  • Signal emitter renames the new temporary file to the well-known filename. This clobbers the old lock file but the waiting receivers all retain references to it.
  • Signal emitter closes the old lock file. This also releases the lock.
  • Signal receivers all wake up because now they can obtain their read locks.
  • Signal receivers should close the file they've just obtained a lock on. It won't be used again. If they want to wait for the condition to happen again they should reopen the file.

In the signal emitter, the temporary lock file which has been renamed over top of the original lock file now becomes the new current lock file.

Option using network multicast

Have the receivers join a multicast group and wait for packets. Have the signal emitter send UDP packets to that multicast group.

You can bind both the sending and receiving UDP sockets to the loopback interface if you want it to use only host-local communication.

OTHER TIPS

In the end I used a bound unix domain socket. The owner keeps an array of client FDs and sends each a message when there is an event.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top