+//
+// Expose the process/pid map to the outside
+//
+Process *Server::findPid(pid_t pid) const
+{
+ PidMap::const_iterator it = mPids.find(pid);
+ return (it == mPids.end()) ? NULL : it->second;
+}
+
+
+//
+// Set delayed shutdown mode
+//
+void Server::waitForClients(bool waiting)
+{
+ mWaitForClients = waiting;
+}
+
+
+//
+// Begin shutdown processing.
+// We relinquish our primary state authority. From now on, we'll be
+// kept alive (only) by our current clients.
+//
+static FILE *reportFile;
+
+void Server::beginShutdown()
+{
+ StLock<Mutex> _(*this);
+ if (!mWaitForClients) {
+ SECURITYD_SHUTDOWN_NOW();
+ _exit(0);
+ } else {
+ if (!mShuttingDown) {
+ mShuttingDown = true;
+ Session::invalidateAuthHosts();
+ SECURITYD_SHUTDOWN_BEGIN();
+ if (verbosity() >= 2) {
+ reportFile = fopen("/var/log/securityd-shutdown.log", "w");
+ shutdownSnitch();
+ }
+ }
+ }
+}
+
+
+//
+// During shutdown, we report residual clients to dtrace, and allow a state dump
+// for debugging.
+// We don't bother locking for the shuttingDown() check; it's a latching boolean
+// and we'll be good enough without a lock.
+//
+void Server::eventDone()
+{
+ if (this->shuttingDown()) {
+ StLock<Mutex> lazy(*this, false); // lazy lock acquisition
+ if (SECURITYD_SHUTDOWN_COUNT_ENABLED()) {
+ lazy.lock();
+ SECURITYD_SHUTDOWN_COUNT(mProcesses.size(), VProc::Transaction::debugCount());
+ }
+ if (verbosity() >= 2) {
+ lazy.lock();
+ shutdownSnitch();
+ }
+ IFDUMPING("shutdown", NodeCore::dumpAll());
+ }
+}
+
+
+void Server::shutdownSnitch()
+{
+ time_t now;
+ time(&now);
+ fprintf(reportFile, "%.24s %d residual clients:\n", ctime(&now), int(mPids.size()));
+ for (PidMap::const_iterator it = mPids.begin(); it != mPids.end(); ++it)
+ if (SecCodeRef clientCode = it->second->processCode()) {
+ CFRef<CFURLRef> path;
+ OSStatus rc = SecCodeCopyPath(clientCode, kSecCSDefaultFlags, &path.aref());
+ if (path)
+ fprintf(reportFile, " %s (%d)\n", cfString(path).c_str(), it->first);
+ else
+ fprintf(reportFile, "pid=%d (error %d)\n", it->first, int32_t(rc));
+ }
+ fprintf(reportFile, "\n");
+ fflush(reportFile);
+}
+
+