[launchd-changes] [23275] trunk/launchd/src/launchd_core_logic.c
source_changes at macosforge.org
source_changes at macosforge.org
Thu Jun 7 16:22:31 PDT 2007
Revision: 23275
http://trac.macosforge.org/projects/launchd/changeset/23275
Author: zarzycki at apple.com
Date: 2007-06-07 16:22:31 -0700 (Thu, 07 Jun 2007)
Log Message:
-----------
<rdar://problem/5190661> Workaround 4058640 (kqueue timers are pushed out by the amount of time the machine was asleep)
Modified Paths:
--------------
trunk/launchd/src/launchd_core_logic.c
Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c 2007-06-07 23:00:50 UTC (rev 23274)
+++ trunk/launchd/src/launchd_core_logic.c 2007-06-07 23:22:31 UTC (rev 23275)
@@ -166,15 +166,21 @@
static void socketgroup_setup(launch_data_t obj, const char *key, void *context);
struct calendarinterval {
+ LIST_ENTRY(calendarinterval) global_sle;
SLIST_ENTRY(calendarinterval) sle;
+ job_t job;
struct tm when;
+ time_t when_next;
};
+static LIST_HEAD(, calendarinterval) sorted_calendar_events;
+
static bool calendarinterval_new(job_t j, struct tm *w);
static bool calendarinterval_new_from_obj(job_t j, launch_data_t obj);
static void calendarinterval_delete(job_t j, struct calendarinterval *ci);
static void calendarinterval_setalarm(job_t j, struct calendarinterval *ci);
-static void calendarinterval_callback(job_t j, void *ident);
+static void calendarinterval_callback(void);
+static void calendarinterval_sanity_check(void);
struct envitem {
SLIST_ENTRY(envitem) sle;
@@ -1792,6 +1798,8 @@
if (j->unload_at_mig_return) {
job_remove(j);
}
+
+ calendarinterval_sanity_check();
}
void
@@ -2097,7 +2105,7 @@
job_kill(j);
}
} else {
- calendarinterval_callback(j, ident);
+ job_assumes(j, false);
}
}
@@ -2143,6 +2151,8 @@
switch (kev->ident) {
case SIGTERM:
return launchd_shutdown();
+ case SIGUSR1:
+ return calendarinterval_callback();
default:
return (void)jobmgr_assumes(jm, false);
}
@@ -2154,7 +2164,11 @@
jobmgr_dispatch_all_semaphores(jm);
break;
case EVFILT_TIMER:
- jobmgr_log(jm, LOG_NOTICE, "Still alive with %u children.", total_children);
+ if (kev->ident == (uintptr_t)&sorted_calendar_events) {
+ calendarinterval_callback();
+ } else {
+ jobmgr_log(jm, LOG_NOTICE, "Still alive with %u children.", total_children);
+ }
break;
default:
return (void)jobmgr_assumes(jm, false);
@@ -2713,6 +2727,8 @@
void
calendarinterval_setalarm(job_t j, struct calendarinterval *ci)
{
+ static time_t last_list_head_when;
+ struct calendarinterval *ci_iter, *ci_prev = NULL;
time_t later;
later = cronemu(ci->when.tm_mon, ci->when.tm_mday, ci->when.tm_hour, ci->when.tm_min);
@@ -2727,11 +2743,46 @@
}
}
- if (-1 == kevent_mod((uintptr_t)ci, EVFILT_TIMER, EV_ADD, NOTE_ABSOLUTE|NOTE_SECONDS, later, j)) {
- job_log_error(j, LOG_ERR, "adding kevent alarm");
- } else {
- job_log(j, LOG_INFO, "scheduled to run again at %s", ctime(&later));
+ ci->when_next = later;
+
+ LIST_FOREACH(ci_iter, &sorted_calendar_events, global_sle) {
+ if (ci->when_next < ci_iter->when_next) {
+ LIST_INSERT_BEFORE(ci_iter, ci, global_sle);
+ break;
+ }
+
+ ci_prev = ci_iter;
}
+
+ if (ci_iter == NULL) {
+ /* ci must want to fire after every other timer, or there are no timers */
+
+ if (LIST_EMPTY(&sorted_calendar_events)) {
+ LIST_INSERT_HEAD(&sorted_calendar_events, ci, global_sle);
+ } else {
+ LIST_INSERT_AFTER(ci_prev, ci, global_sle);
+ }
+ }
+
+ if (last_list_head_when == LIST_FIRST(&sorted_calendar_events)->when_next) {
+ return;
+ }
+
+ last_list_head_when = LIST_FIRST(&sorted_calendar_events)->when_next;
+
+ if (job_assumes(j, kevent_mod((uintptr_t)&sorted_calendar_events, EVFILT_TIMER, EV_ADD, NOTE_ABSOLUTE|NOTE_SECONDS, last_list_head_when, root_jobmgr) != -1)) {
+ char time_string[100];
+ size_t time_string_len;
+
+ ctime_r(&later, time_string);
+ time_string_len = strlen(time_string);
+
+ if (time_string_len && time_string[time_string_len - 1] == '\n') {
+ time_string[time_string_len - 1] = '\0';
+ }
+
+ job_log(j, LOG_INFO, "Scheduled to run again at %s", time_string);
+ }
}
static void
@@ -3081,9 +3132,10 @@
}
ci->when = *w;
+ ci->job = j;
SLIST_INSERT_HEAD(&j->cal_intervals, ci, sle);
-
+
calendarinterval_setalarm(j, ci);
return true;
@@ -3092,26 +3144,39 @@
void
calendarinterval_delete(job_t j, struct calendarinterval *ci)
{
- job_assumes(j, kevent_mod((uintptr_t)ci, EVFILT_TIMER, EV_DELETE, 0, 0, NULL) != -1);
-
SLIST_REMOVE(&j->cal_intervals, ci, calendarinterval, sle);
+ LIST_REMOVE(ci, global_sle);
free(ci);
}
void
-calendarinterval_callback(job_t j, void *ident)
+calendarinterval_sanity_check(void)
{
- struct calendarinterval *ci;
+ struct calendarinterval *ci = LIST_FIRST(&sorted_calendar_events);
+ time_t now = time(NULL);
- SLIST_FOREACH(ci, &j->cal_intervals, sle) {
- if (ci == ident) {
+ if (ci && ci->when_next < now) {
+ jobmgr_assumes(root_jobmgr, kill(getpid(), SIGUSR1) != -1);
+ }
+}
+
+void
+calendarinterval_callback(void)
+{
+ struct calendarinterval *ci, *ci_next;
+ time_t now = time(NULL);
+
+ LIST_FOREACH_SAFE(ci, &sorted_calendar_events, global_sle, ci_next) {
+ job_t j = ci->job;
+
+ if (ci->when_next >= now) {
break;
}
- }
- if (job_assumes(j, ci != NULL)) {
+ LIST_REMOVE(ci, global_sle);
calendarinterval_setalarm(j, ci);
+
j->start_pending = true;
job_dispatch(j, false);
}
@@ -3931,6 +3996,7 @@
if (!jm) {
jobmgr_assumes(jmr, kevent_mod(SIGTERM, EVFILT_SIGNAL, EV_ADD, 0, 0, jmr) != -1);
+ jobmgr_assumes(jmr, kevent_mod(SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, jmr) != -1);
jobmgr_assumes(jmr, kevent_mod(0, EVFILT_FS, EV_ADD, VQ_MOUNT|VQ_UNMOUNT|VQ_UPDATE, 0, jmr) != -1);
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/launchd-changes/attachments/20070607/e3e6319f/attachment.html
More information about the launchd-changes
mailing list