Compare commits

..

4 Commits

Author SHA1 Message Date
Anita Zhang b219d193a2
Merge pull request #13884 from poettering/event-fd-close-fix
sd-event: don't invalidate source type on disconnect
2019-10-30 15:58:36 -07:00
Christian Rebischke 9d9010f2e9 add systemd logo to README.md
The logo in the readme is hosted by github as the systemd group avatar.

Signed-off-by: Christian Rebischke <chris@nullday.de>
2019-10-30 23:22:07 +01:00
Zbigniew Jędrzejewski-Szmek be75c86dc6 calendarspec: fix calculation of timespec iterations that fall onto a DST change
If we tested a candidate time that would fall onto the DST change, and we
realized that it is now a valid time ('cause the given "hour" is missing),
we would jump to to beginning of the next bigger time period, i.e. the next
day.

mktime_or_timegm() already tells us what the next valid time is, so let's reuse
this, and continue the calculations at this point. This should allow us to
correctly jump over DST changes, but also leap seconds and similar.  It should
be OK even multiple days were removed from calendar, similarly to the
Gregorian-Julian transition. By reusing the information from normalization, we
don't have to make assumptions what the next valid time is.

Fixes #13745.

$ TZ=Australia/Sydney faketime '2019-10-06 01:50' build/systemd-analyze calendar 0/1:0/1 --iterations 20 | grep Iter
       Iter. #2: Sun 2019-10-06 01:52:00 AEST
       Iter. #3: Sun 2019-10-06 01:53:00 AEST
       Iter. #4: Sun 2019-10-06 01:54:00 AEST
       Iter. #5: Sun 2019-10-06 01:55:00 AEST
       Iter. #6: Sun 2019-10-06 01:56:00 AEST
       Iter. #7: Sun 2019-10-06 01:57:00 AEST
       Iter. #8: Sun 2019-10-06 01:58:00 AEST
       Iter. #9: Sun 2019-10-06 01:59:00 AEST
      Iter. #10: Sun 2019-10-06 03:00:00 AEDT
      Iter. #11: Sun 2019-10-06 03:01:00 AEDT
      Iter. #12: Sun 2019-10-06 03:02:00 AEDT
      Iter. #13: Sun 2019-10-06 03:03:00 AEDT
      Iter. #14: Sun 2019-10-06 03:04:00 AEDT
      Iter. #15: Sun 2019-10-06 03:05:00 AEDT
      Iter. #16: Sun 2019-10-06 03:06:00 AEDT
      Iter. #17: Sun 2019-10-06 03:07:00 AEDT
      Iter. #18: Sun 2019-10-06 03:08:00 AEDT
      Iter. #19: Sun 2019-10-06 03:09:00 AEDT
      Iter. #20: Sun 2019-10-06 03:10:00 AEDT

$ TZ=Australia/Sydney faketime 2019-10-06 build/systemd-analyze calendar 2/4:30 --iterations=3
  Original form: 2/4:30
Normalized form: *-*-* 02/4:30:00
    Next elapse: Sun 2019-10-06 06:30:00 AEDT
       (in UTC): Sat 2019-10-05 19:30:00 UTC
       From now: 5h 29min left
       Iter. #2: Sun 2019-10-06 10:30:00 AEDT
       (in UTC): Sat 2019-10-05 23:30:00 UTC
       From now: 9h left
       Iter. #3: Sun 2019-10-06 14:30:00 AEDT
       (in UTC): Sun 2019-10-06 03:30:00 UTC
       From now: 13h left
2019-10-30 17:57:01 +01:00
Lennart Poettering f598255951 sd-event: don't invalidate source type on disconnect
This fixes fd closing if fd ownership is requested.
2019-10-30 17:43:57 +01:00
3 changed files with 39 additions and 21 deletions

View File

@ -1,5 +1,7 @@
# systemd - System and Service Manager # systemd - System and Service Manager
![systemd logo](https://avatars0.githubusercontent.com/u/1918868?s=200&v=4)
<a href="https://in.waw.pl/systemd-github-state/systemd-systemd-issues.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-issues-small.svg" alt="Count of open issues over time"></a> <a href="https://in.waw.pl/systemd-github-state/systemd-systemd-issues.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-issues-small.svg" alt="Count of open issues over time"></a>
<a href="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests-small.svg" alt="Count of open pull requests over time"></a> <a href="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests-small.svg" alt="Count of open pull requests over time"></a>
[![Semaphore CI Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)<br/> [![Semaphore CI Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)<br/>

View File

@ -771,11 +771,13 @@ static void source_disconnect(sd_event_source *s) {
event = s->event; event = s->event;
s->type = _SOURCE_EVENT_SOURCE_TYPE_INVALID;
s->event = NULL; s->event = NULL;
LIST_REMOVE(sources, event->sources, s); LIST_REMOVE(sources, event->sources, s);
event->n_sources--; event->n_sources--;
/* Note that we don't invalidate the type here, since we still need it in order to close the fd or
* pidfd associated with this event source, which we'll do only on source_free(). */
if (!s->floating) if (!s->floating)
sd_event_unref(event); sd_event_unref(event);
} }

View File

@ -1146,31 +1146,32 @@ static int find_matching_component(const CalendarSpec *spec, const CalendarCompo
return r; return r;
} }
static bool tm_out_of_bounds(const struct tm *tm, bool utc) { static int tm_within_bounds(struct tm *tm, bool utc) {
struct tm t; struct tm t;
assert(tm); assert(tm);
t = *tm;
if (mktime_or_timegm(&t, utc) < 0)
return true;
/* /*
* Set an upper bound on the year so impossible dates like "*-02-31" * Set an upper bound on the year so impossible dates like "*-02-31"
* don't cause find_next() to loop forever. tm_year contains years * don't cause find_next() to loop forever. tm_year contains years
* since 1900, so adjust it accordingly. * since 1900, so adjust it accordingly.
*/ */
if (tm->tm_year + 1900 > MAX_YEAR) if (tm->tm_year + 1900 > MAX_YEAR)
return true; return -ERANGE;
t = *tm;
if (mktime_or_timegm(&t, utc) < 0)
return negative_errno();
/* Did any normalization take place? If so, it was out of bounds before */ /* Did any normalization take place? If so, it was out of bounds before */
return bool good = t.tm_year == tm->tm_year &&
t.tm_year != tm->tm_year || t.tm_mon == tm->tm_mon &&
t.tm_mon != tm->tm_mon || t.tm_mday == tm->tm_mday &&
t.tm_mday != tm->tm_mday || t.tm_hour == tm->tm_hour &&
t.tm_hour != tm->tm_hour || t.tm_min == tm->tm_min &&
t.tm_min != tm->tm_min || t.tm_sec == tm->tm_sec;
t.tm_sec != tm->tm_sec; if (!good)
*tm = t;
return good;
} }
static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) { static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) {
@ -1217,7 +1218,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
} }
if (r < 0) if (r < 0)
return r; return r;
if (tm_out_of_bounds(&c, spec->utc)) if (tm_within_bounds(&c, spec->utc) <= 0)
return -ENOENT; return -ENOENT;
c.tm_mon += 1; c.tm_mon += 1;
@ -1228,23 +1229,27 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
c.tm_mday = 1; c.tm_mday = 1;
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
} }
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) {
c.tm_year++; c.tm_year++;
c.tm_mon = 0; c.tm_mon = 0;
c.tm_mday = 1; c.tm_mday = 1;
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue; continue;
} }
if (r == 0)
continue;
r = find_matching_component(spec, spec->day, &c, &c.tm_mday); r = find_matching_component(spec, spec->day, &c, &c.tm_mday);
if (r > 0) if (r > 0)
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) {
c.tm_mon++; c.tm_mon++;
c.tm_mday = 1; c.tm_mday = 1;
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue; continue;
} }
if (r == 0)
continue;
if (!matches_weekday(spec->weekdays_bits, &c, spec->utc)) { if (!matches_weekday(spec->weekdays_bits, &c, spec->utc)) {
c.tm_mday++; c.tm_mday++;
@ -1255,31 +1260,40 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
r = find_matching_component(spec, spec->hour, &c, &c.tm_hour); r = find_matching_component(spec, spec->hour, &c, &c.tm_hour);
if (r > 0) if (r > 0)
c.tm_min = c.tm_sec = tm_usec = 0; c.tm_min = c.tm_sec = tm_usec = 0;
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) {
c.tm_mday++; c.tm_mday++;
c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0;
continue; continue;
} }
if (r == 0)
/* The next hour we set might be missing if there
* are time zone changes. Let's try again starting at
* normalized time. */
continue;
r = find_matching_component(spec, spec->minute, &c, &c.tm_min); r = find_matching_component(spec, spec->minute, &c, &c.tm_min);
if (r > 0) if (r > 0)
c.tm_sec = tm_usec = 0; c.tm_sec = tm_usec = 0;
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) {
c.tm_hour++; c.tm_hour++;
c.tm_min = c.tm_sec = tm_usec = 0; c.tm_min = c.tm_sec = tm_usec = 0;
continue; continue;
} }
if (r == 0)
continue;
c.tm_sec = c.tm_sec * USEC_PER_SEC + tm_usec; c.tm_sec = c.tm_sec * USEC_PER_SEC + tm_usec;
r = find_matching_component(spec, spec->microsecond, &c, &c.tm_sec); r = find_matching_component(spec, spec->microsecond, &c, &c.tm_sec);
tm_usec = c.tm_sec % USEC_PER_SEC; tm_usec = c.tm_sec % USEC_PER_SEC;
c.tm_sec /= USEC_PER_SEC; c.tm_sec /= USEC_PER_SEC;
if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { if (r < 0 || (r = tm_within_bounds(&c, spec->utc)) < 0) {
c.tm_min++; c.tm_min++;
c.tm_sec = tm_usec = 0; c.tm_sec = tm_usec = 0;
continue; continue;
} }
if (r == 0)
continue;
*tm = c; *tm = c;
*usec = tm_usec; *usec = tm_usec;