[30313] trunk/base/src/programs/daemondo/main.c
source_changes at macosforge.org
source_changes at macosforge.org
Wed Oct 24 05:58:54 PDT 2007
Revision: 30313
http://trac.macosforge.org/projects/macports/changeset/30313
Author: jberry at macports.org
Date: 2007-10-24 05:58:54 -0700 (Wed, 24 Oct 2007)
Log Message:
-----------
Improve Daemondo to use kqueue/kevent to watch for the death of the target
process. Previously Daemondo relied on child death signals, which are given
only for direct offspring, and not grandchildren, etc. The use of the kevents
now gives notice when the targetted process is not direct offspring.
Note: these changes may introduce compatibility issues for Panther, or even
Tiger, since I have not yet tested in those environments. They may also introduce
compilation problems on platforms for which there is no kqueue support at all.
Bug reports are welcome.
Modified Paths:
--------------
trunk/base/src/programs/daemondo/main.c
Modified: trunk/base/src/programs/daemondo/main.c
===================================================================
--- trunk/base/src/programs/daemondo/main.c 2007-10-24 11:20:09 UTC (rev 30312)
+++ trunk/base/src/programs/daemondo/main.c 2007-10-24 12:58:54 UTC (rev 30313)
@@ -67,6 +67,9 @@
#include <fcntl.h>
#include <stdarg.h>
#include <time.h>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
#include <sys/wait.h>
#include <mach/mach.h>
@@ -105,6 +108,8 @@
int terminating = 0; // TRUE if we're terminating
pid_t runningPid = 0; // Current running pid (0 while stopped, -1 if we don't know pid)
+int kqfd = 0; // Kqueue file descriptor
+
mach_port_t sigChild_m_port = 0; // Mach port to send signals through
mach_port_t sigGeneric_m_port = 0; // Mach port to send signals through
@@ -163,7 +168,7 @@
void
DoVersion(void)
{
- printf("daemondo, version 1.0d3\n\n");
+ printf("daemondo, version 1.1\n\n");
}
@@ -333,23 +338,59 @@
pid_t pid = -1;
while ((pid = CheckForValidPidFile()) == -1 && (patience - CFAbsoluteTimeGetCurrent() > 0))
sleep(1);
+
+ if (verbosity >= 3)
+ LogMessage("Discovered pid %d from pidfile %s\n", pid, pidFile);
return pid;
}
+
void
+MonitorChild(pid_t childPid)
+{
+ runningPid = childPid;
+
+ if (runningPid != 0 && runningPid != -1) {
+ if (verbosity >=3 )
+ LogMessage("Start monitoring of pid %d via kevent\n", runningPid);
+
+ // Monitor the process deaths for that pid
+ struct kevent ke;
+ EV_SET(&ke, childPid, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, NULL);
+ if (-1 == kevent(kqfd, &ke, 1, NULL, 0, NULL))
+ LogMessage("Could not monitor kevent for pid %d (%d)\n", runningPid, errno);
+ }
+}
+
+
+void
+UnmonitorChild()
+{
+ runningPid = 0;
+}
+
+
+int
+MonitoringChild()
+{
+ return runningPid != 0;
+}
+
+
+void
ProcessChildDeath(pid_t childPid)
{
// Take special note if process runningPid dies
if (runningPid != 0 && runningPid != -1 && childPid == runningPid)
{
if (verbosity >= 3)
- LogMessage("Running process id %d has died.\n", childPid);
+ LogMessage("Target process id %d has died.\n", childPid);
+ UnmonitorChild();
DestroyPidFile();
-
- runningPid = 0;
+
CFRunLoopStop(CFRunLoopGetCurrent());
}
}
@@ -509,11 +550,11 @@
}
// If we have a pid, then begin tracking it
- runningPid = pid;
+ MonitorChild(pid);
if (pid != 0 && pid != -1)
{
if (verbosity >= 1)
- LogMessage("process id %d\n", pid);
+ LogMessage("Target process id is %d\n", pid);
// Create a pid file if we need to
CreatePidFile();
@@ -569,7 +610,7 @@
}
// We've executed stop-cmd, so we assume any runningPid process is gone
- runningPid = 0;
+ UnmonitorChild();
DestroyPidFile();
}
@@ -767,6 +808,32 @@
}
+void KQueueCallBack (CFSocketRef socketRef, CFSocketCallBackType type,
+ CFDataRef address, const void *data, void *context)
+{
+ int fd = CFSocketGetNative(socketRef);
+
+ struct kevent event;
+ memset(&event, 0x00, sizeof(struct kevent));
+
+ if (kevent(fd, NULL, 0, &event, 1, NULL) == -1) {
+ LogMessage("Couldn't get kevent. Error %d/%s\n", errno, strerror(errno));
+ } else {
+ if (event.fflags & NOTE_EXIT) {
+
+ pid_t pid = event.ident;
+
+ if (verbosity >= 3)
+ LogMessage("Received kevent: pid %d has exited\n", pid);
+
+ ProcessChildDeath(pid);
+ } else
+ LogMessage("Unexpected kevent received: %d\n", event.fflags);
+ }
+
+}
+
+
void
AddNotificationToCenter(const void* value, void* context)
{
@@ -822,6 +889,8 @@
int status = 0;
+ if (verbosity >= 3)
+ LogMessage("Initializing; daemondo pid is %d\n", getpid());
// === Setup Notifications of Changes to System Configuration ===
// Create a new SCDynamicStore session and an associated runloop source, adding it default mode
@@ -858,11 +927,21 @@
CFRunLoopSourceRef sigChildSrc = CFMachPortCreateRunLoopSource(NULL, sigChildPort, 0);
CFRunLoopSourceRef sigGenericSrc = CFMachPortCreateRunLoopSource(NULL, sigGenericPort, 0);
- // Add only the child signal source to the childwatch mode
+
+ // === Setup kevent notifications of process death
+ kqfd = kqueue();
+ CFSocketRef kqSocket = CFSocketCreateWithNative(NULL, kqfd,
+ kCFSocketReadCallBack, KQueueCallBack, NULL);
+ CFRunLoopSourceRef kqueueSrc = CFSocketCreateRunLoopSource(NULL, kqSocket, 0);
+
+
+ // Add only the child signal sources to the childwatch mode
CFRunLoopAddSource(CFRunLoopGetCurrent(), sigChildSrc, kChildWatchMode);
-
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), kqueueSrc, kChildWatchMode);
+
// Add both child and generic signal sources to the default mode
CFRunLoopAddSource(CFRunLoopGetCurrent(), sigChildSrc, kCFRunLoopDefaultMode);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), kqueueSrc, kCFRunLoopDefaultMode);
CFRunLoopAddSource(CFRunLoopGetCurrent(), sigGenericSrc, kCFRunLoopDefaultMode);
// Install signal handlers
@@ -878,12 +957,18 @@
// Start the daemon
status = Start();
+ if (verbosity >= 3)
+ LogMessage("Start event loop\n");
+
// Run the run loop until we stop it, or until the process we're tracking stops
- while (status == 0 && !terminating && runningPid != 0)
+ while (status == 0 && !terminating && MonitoringChild())
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 99999999.0, true);
+ if (verbosity >= 3)
+ LogMessage("End event loop\n");
+
- // === Tear Down ==
+ // === Tear Down (we don't really need to do all of this) ===
// The daemon should by now have either been stopped, or stopped of its own accord
// Remove signal handlers
@@ -894,16 +979,25 @@
sigChild_m_port = 0;
sigGeneric_m_port = 0;
- // Tear down signal handling infrastructure
+ // Remove run loop sources
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), sigChildSrc, kChildWatchMode);
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), kqueueSrc, kChildWatchMode);
+
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), sigChildSrc, kCFRunLoopDefaultMode);
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), kqueueSrc, kCFRunLoopDefaultMode);
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), sigGenericSrc, kCFRunLoopDefaultMode);
+ // Tear down signal handling infrastructure
CFRelease(sigChildSrc);
CFRelease(sigGenericSrc);
CFRelease(sigChildPort);
CFRelease(sigGenericPort);
+
+ // Tear down kqueue infrastructure
+ CFRelease(kqueueSrc);
+ CFRelease(kqSocket);
+ close(kqfd);
// Tear down DynamicStore stuff
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), dsSrc, kCFRunLoopDefaultMode);
@@ -919,6 +1013,9 @@
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(powerRef), kCFRunLoopDefaultMode);
IODeregisterForSystemPower(&pwrNotifier);
+ if (verbosity >= 3)
+ LogMessage("Terminating\n");
+
return status;
}
@@ -1055,7 +1152,7 @@
{
int optindex = 0;
int ret = getopt_long(argc, argv, ":s:k:r:l:hvV", longopts, &optindex);
- int opt = (ret == '?') ? optopt : ret;
+ int opt = ret;
switch (opt)
{
case ':':
@@ -1140,6 +1237,10 @@
pidStyle = kPidStyleFileAuto;
else if (0 == strcasecmp(optarg, "fileclean"))
pidStyle = kPidStyleFileClean;
+ else {
+ status = 1;
+ LogMessage("Unexpected pid style %s\n", optarg);
+ }
break;
case kPidFileOpt:
@@ -1173,6 +1274,11 @@
case 'V':
DoVersion();
break;
+
+ default:
+ LogMessage("unexpected parameter: %s\n", argv[optind]);
+ status = 1;
+ break;
}
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macports-changes/attachments/20071024/85502472/attachment.html
More information about the macports-changes
mailing list