Systemwide application singletons

Application singletons are normally per-userid. Different userids can start the same application and run a singleton application process under that userid. By default, a started application singleton would only connect to any existing application process that runs under the same real userid. An existing application singleton process running under some userid will not prevent a different userid from starting its own singleton process.

It's possible to have a systemwide application singleton, one singleton that spawns a thread and connects to any other userid that starts the same application.

x::singletonapp::instance instance=x::singletonapp::create(factory, 0, 0755);

x::singletonapp::create() takes two optional parameters: a system userid, and the permissions for the singleton's filesystem socket. They default to the real userid of the process that invoked it, and 0700, and has the following effect:

The filesystem socket gets created in a temporary directory whose default permissions are 0700, preventing connections from processes that run under a different userid. For a systemwide singleton, it must specify permissions of 0755, in order to accept connections from processes from all userids. In all cases, even with per-userid singletons, additional credentials verifications are needed. validate_peer() also does a sanity check that the peer is running the same executable, and not just it's a process with the same userid. With systemwide singletons, validate_peer() only checks that it's the same executable:

uid_t uid=x::singletonapp::validate_peer(connection, false);

validate_peer(), by default, requires that the socket's peer must have the same real userid as the process that invokes it, otherwise an exception gets thrown. A single systemwide singleton can spawn threads after other real userids started the singleton process, so this check gets disabled by setting the second, optional, parameter to validate_peer() to false. validate_peer() returns the peer's system userid, which can be processed in any application-specific manner.


new_thread() gets invoked, and the subsequent thread runs as, using the real userid of the process that started the singleton process, notwithstanding the userid of the other singleton process that's connected to the one that's running the threads.