chiark / gitweb /
bus: properly handle if new objects are installed in the node tree while we are dispa...
[elogind.git] / src / journal / sd-journal.c
index 2bad243ea115dc08919af662f49cc47b45488911..3ccb14a242832fa2b4d0e0c903313d40004bed16 100644 (file)
@@ -33,6 +33,7 @@
 #include "journal-file.h"
 #include "hashmap.h"
 #include "list.h"
+#include "strv.h"
 #include "path-util.h"
 #include "lookup3.h"
 #include "compress.h"
 
 #define DEFAULT_DATA_THRESHOLD (64*1024)
 
+static bool journal_pid_changed(sd_journal *j) {
+        assert(j);
+
+        /* We don't support people creating a journal object and
+         * keeping it around over a fork(). Let's complain. */
+
+        return j->original_pid != getpid();
+}
+
 /* We return an error here only if we didn't manage to
    memorize the real error. */
 static int set_put_error(sd_journal *j, int r) {
@@ -101,7 +111,8 @@ static void init_location(Location *l, LocationType type, JournalFile *f, Object
         l->seqnum_set = l->realtime_set = l->monotonic_set = l->xor_hash_set = true;
 }
 
-static void set_location(sd_journal *j, LocationType type, JournalFile *f, Object *o, uint64_t offset) {
+static void set_location(sd_journal *j, LocationType type, JournalFile *f, Object *o,
+                         direction_t direction, uint64_t offset) {
         assert(j);
         assert(type == LOCATION_DISCRETE || type == LOCATION_SEEK);
         assert(f);
@@ -109,12 +120,10 @@ static void set_location(sd_journal *j, LocationType type, JournalFile *f, Objec
 
         init_location(&j->current_location, type, f, o);
 
-        if (j->current_file)
-                j->current_file->current_offset = 0;
-
         j->current_file = f;
         j->current_field = 0;
 
+        f->last_direction = direction;
         f->current_offset = offset;
 }
 
@@ -163,7 +172,7 @@ static bool same_field(const void *_a, size_t s, const void *_b, size_t t) {
                         return true;
         }
 
-        return true;
+        assert_not_reached("\"=\" not found");
 }
 
 static Match *match_new(Match *p, MatchType t) {
@@ -177,7 +186,7 @@ static Match *match_new(Match *p, MatchType t) {
 
         if (p) {
                 m->parent = p;
-                LIST_PREPEND(Match, matches, p->matches, m);
+                LIST_PREPEND(matches, p->matches, m);
         }
 
         return m;
@@ -190,7 +199,7 @@ static void match_free(Match *m) {
                 match_free(m->matches);
 
         if (m->parent)
-                LIST_REMOVE(Match, matches, m->parent->matches, m);
+                LIST_REMOVE(matches, m->parent->matches, m);
 
         free(m->data);
         free(m);
@@ -209,6 +218,8 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size)
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         if (!data)
                 return -EINVAL;
@@ -303,7 +314,10 @@ fail:
 }
 
 _public_ int sd_journal_add_conjunction(sd_journal *j) {
-        assert(j);
+        if (!j)
+                return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         if (!j->level0)
                 return 0;
@@ -321,7 +335,10 @@ _public_ int sd_journal_add_conjunction(sd_journal *j) {
 }
 
 _public_ int sd_journal_add_disjunction(sd_journal *j) {
-        assert(j);
+        if (!j)
+                return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         if (!j->level0)
                 return 0;
@@ -345,7 +362,7 @@ static char *match_make_string(Match *m) {
         bool enclose = false;
 
         if (!m)
-                return strdup("");
+                return strdup("none");
 
         if (m->type == MATCH_DISCRETE)
                 return strndup(m->data, m->size);
@@ -371,10 +388,8 @@ static char *match_make_string(Match *m) {
                         p = k;
 
                         enclose = true;
-                } else {
-                        free(p);
+                } else
                         p = t;
-                }
         }
 
         if (enclose) {
@@ -393,7 +408,6 @@ char *journal_make_match_string(sd_journal *j) {
 }
 
 _public_ void sd_journal_flush_matches(sd_journal *j) {
-
         if (!j)
                 return;
 
@@ -587,52 +601,47 @@ static int next_for_match(
                         if (r < 0)
                                 return r;
                         else if (r > 0) {
-                                if (np == 0 || (direction == DIRECTION_DOWN ? np > cp : np < cp))
+                                if (np == 0 || (direction == DIRECTION_DOWN ? cp < np : cp > np))
                                         np = cp;
                         }
                 }
 
+                if (np == 0)
+                        return 0;
+
         } else if (m->type == MATCH_AND_TERM) {
-                Match *i;
-                bool continue_looking;
+                Match *i, *last_moved;
 
                 /* Always jump to the next matching entry and repeat
-                 * this until we fine and offset that matches for all
+                 * this until we find an offset that matches for all
                  * matches. */
 
                 if (!m->matches)
                         return 0;
 
-                np = 0;
-                do {
-                        continue_looking = false;
+                r = next_for_match(j, m->matches, f, after_offset, direction, NULL, &np);
+                if (r <= 0)
+                        return r;
 
-                        LIST_FOREACH(matches, i, m->matches) {
-                                uint64_t cp, limit;
+                assert(direction == DIRECTION_DOWN ? np >= after_offset : np <= after_offset);
+                last_moved = m->matches;
 
-                                if (np == 0)
-                                        limit = after_offset;
-                                else if (direction == DIRECTION_DOWN)
-                                        limit = MAX(np, after_offset);
-                                else
-                                        limit = MIN(np, after_offset);
+                LIST_LOOP_BUT_ONE(matches, i, m->matches, last_moved) {
+                        uint64_t cp;
 
-                                r = next_for_match(j, i, f, limit, direction, NULL, &cp);
-                                if (r <= 0)
-                                        return r;
+                        r = next_for_match(j, i, f, np, direction, NULL, &cp);
+                        if (r <= 0)
+                                return r;
 
-                                if ((direction == DIRECTION_DOWN ? cp >= after_offset : cp <= after_offset) &&
-                                    (np == 0 || (direction == DIRECTION_DOWN ? cp > np : cp < np))) {
-                                        np = cp;
-                                        continue_looking = true;
-                                }
+                        assert(direction == DIRECTION_DOWN ? cp >= np : cp <= np);
+                        if (direction == DIRECTION_DOWN ? cp > np : cp < np) {
+                                np = cp;
+                                last_moved = i;
                         }
-
-                } while (continue_looking);
+                }
         }
 
-        if (np == 0)
-                return 0;
+        assert(np > 0);
 
         r = journal_file_move_to_object(f, OBJECT_ENTRY, np, &n);
         if (r < 0)
@@ -737,7 +746,7 @@ static int find_location_for_match(
                         if (r <= 0)
                                 return r;
 
-                        if (np == 0 || (direction == DIRECTION_DOWN ? np < cp : np > cp))
+                        if (np == 0 || (direction == DIRECTION_DOWN ? cp > np : cp < np))
                                 np = cp;
                 }
 
@@ -817,7 +826,7 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc
         assert(j);
         assert(f);
 
-        if (f->current_offset > 0) {
+        if (f->last_direction == direction && f->current_offset > 0) {
                 cp = f->current_offset;
 
                 r = journal_file_move_to_object(f, OBJECT_ENTRY, cp, &c);
@@ -833,7 +842,7 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc
                         return r;
         }
 
-        /* OK, we found the spot, now let's advance until to an entry
+        /* OK, we found the spot, now let's advance until an entry
          * that is actually different from what we were previously
          * looking at. This is necessary to handle entries which exist
          * in two (or more) journal files, and which shall all be
@@ -877,6 +886,8 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         HASHMAP_FOREACH(f, j->files, i) {
                 bool found;
@@ -895,10 +906,7 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
 
                         k = compare_entry_order(f, o, new_file, new_offset);
 
-                        if (direction == DIRECTION_DOWN)
-                                found = k < 0;
-                        else
-                                found = k > 0;
+                        found = direction == DIRECTION_DOWN ? k < 0 : k > 0;
                 }
 
                 if (found) {
@@ -914,7 +922,7 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
         if (r < 0)
                 return r;
 
-        set_location(j, LOCATION_DISCRETE, new_file, o, new_offset);
+        set_location(j, LOCATION_DISCRETE, new_file, o, direction, new_offset);
 
         return 1;
 }
@@ -932,6 +940,8 @@ static int real_journal_next_skip(sd_journal *j, direction_t direction, uint64_t
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         if (skip == 0) {
                 /* If this is not a discrete skip, then at least
@@ -972,6 +982,8 @@ _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) {
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (!cursor)
                 return -EINVAL;
 
@@ -986,11 +998,11 @@ _public_ int sd_journal_get_cursor(sd_journal *j, char **cursor) {
         sd_id128_to_string(o->entry.boot_id, bid);
 
         if (asprintf(cursor,
-                     "s=%s;i=%llx;b=%s;m=%llx;t=%llx;x=%llx",
-                     sid, (unsigned long long) le64toh(o->entry.seqnum),
-                     bid, (unsigned long long) le64toh(o->entry.monotonic),
-                     (unsigned long long) le64toh(o->entry.realtime),
-                     (unsigned long long) le64toh(o->entry.xor_hash)) < 0)
+                     "s=%s;i=%"PRIx64";b=%s;m=%"PRIx64";t=%"PRIx64";x=%"PRIx64,
+                     sid, le64toh(o->entry.seqnum),
+                     bid, le64toh(o->entry.monotonic),
+                     le64toh(o->entry.realtime),
+                     le64toh(o->entry.xor_hash)) < 0)
                 return -ENOMEM;
 
         return 0;
@@ -1011,6 +1023,8 @@ _public_ int sd_journal_seek_cursor(sd_journal *j, const char *cursor) {
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (isempty(cursor))
                 return -EINVAL;
 
@@ -1110,6 +1124,8 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (isempty(cursor))
                 return -EINVAL;
 
@@ -1188,6 +1204,8 @@ _public_ int sd_journal_test_cursor(sd_journal *j, const char *cursor) {
 _public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t usec) {
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         reset_location(j);
         j->current_location.type = LOCATION_SEEK;
@@ -1201,6 +1219,8 @@ _public_ int sd_journal_seek_monotonic_usec(sd_journal *j, sd_id128_t boot_id, u
 _public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) {
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         reset_location(j);
         j->current_location.type = LOCATION_SEEK;
@@ -1213,6 +1233,8 @@ _public_ int sd_journal_seek_realtime_usec(sd_journal *j, uint64_t usec) {
 _public_ int sd_journal_seek_head(sd_journal *j) {
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         reset_location(j);
         j->current_location.type = LOCATION_HEAD;
@@ -1223,6 +1245,8 @@ _public_ int sd_journal_seek_head(sd_journal *j) {
 _public_ int sd_journal_seek_tail(sd_journal *j) {
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         reset_location(j);
         j->current_location.type = LOCATION_TAIL;
@@ -1242,48 +1266,67 @@ static void check_network(sd_journal *j, int fd) {
                 return;
 
         j->on_network =
-                F_TYPE_CMP(sfs.f_type, CIFS_MAGIC_NUMBER) ||
-                F_TYPE_CMP(sfs.f_type, CODA_SUPER_MAGIC) ||
-                F_TYPE_CMP(sfs.f_type, NCP_SUPER_MAGIC) ||
-                F_TYPE_CMP(sfs.f_type, NFS_SUPER_MAGIC) ||
-                F_TYPE_CMP(sfs.f_type, SMB_SUPER_MAGIC);
+                F_TYPE_EQUAL(sfs.f_type, CIFS_MAGIC_NUMBER) ||
+                F_TYPE_EQUAL(sfs.f_type, CODA_SUPER_MAGIC) ||
+                F_TYPE_EQUAL(sfs.f_type, NCP_SUPER_MAGIC) ||
+                F_TYPE_EQUAL(sfs.f_type, NFS_SUPER_MAGIC) ||
+                F_TYPE_EQUAL(sfs.f_type, SMB_SUPER_MAGIC);
 }
 
-static int add_file(sd_journal *j, const char *prefix, const char *filename) {
-        _cleanup_free_ char *path = NULL;
-        int r;
-        JournalFile *f;
+static bool file_has_type_prefix(const char *prefix, const char *filename) {
+        const char *full, *tilded, *atted;
 
-        assert(j);
-        assert(prefix);
-        assert(filename);
+        full = strappend(prefix, ".journal");
+        tilded = strappenda(full, "~");
+        atted = strappenda(prefix, "@");
 
-        if ((j->flags & SD_JOURNAL_SYSTEM_ONLY) &&
-            !(streq(filename, "system.journal") ||
-              streq(filename, "system.journal~") ||
-              (startswith(filename, "system@") &&
-               (endswith(filename, ".journal") || endswith(filename, ".journal~")))))
-                return 0;
+        return streq(filename, full) ||
+               streq(filename, tilded) ||
+               startswith(filename, atted);
+}
 
-        path = strjoin(prefix, "/", filename, NULL);
-        if (!path)
-                return -ENOMEM;
+static bool file_type_wanted(int flags, const char *filename) {
+        if (!endswith(filename, ".journal") && !endswith(filename, ".journal~"))
+                return false;
+
+        /* no flags set → every type is OK */
+        if (!(flags & (SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER)))
+                return true;
+
+        if (flags & SD_JOURNAL_SYSTEM && file_has_type_prefix("system", filename))
+                return true;
+
+        if (flags & SD_JOURNAL_CURRENT_USER) {
+                char prefix[5 + DECIMAL_STR_MAX(uid_t) + 1];
+
+                assert_se(snprintf(prefix, sizeof(prefix), "user-%lu", (unsigned long) getuid())
+                          < (int) sizeof(prefix));
+
+                if (file_has_type_prefix(prefix, filename))
+                        return true;
+        }
+
+        return false;
+}
+
+static int add_any_file(sd_journal *j, const char *path) {
+        JournalFile *f;
+        int r;
+
+        assert(j);
+        assert(path);
 
         if (hashmap_get(j->files, path))
                 return 0;
 
         if (hashmap_size(j->files) >= JOURNAL_FILES_MAX) {
-                log_debug("Too many open journal files, not adding %s, ignoring.", path);
+                log_warning("Too many open journal files, not adding %s.", path);
                 return set_put_error(j, -ETOOMANYREFS);
         }
 
         r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f);
-        if (r < 0) {
-                if (errno == ENOENT)
-                        return 0;
-
+        if (r < 0)
                 return r;
-        }
 
         /* journal_file_dump(f); */
 
@@ -1302,6 +1345,28 @@ static int add_file(sd_journal *j, const char *prefix, const char *filename) {
         return 0;
 }
 
+static int add_file(sd_journal *j, const char *prefix, const char *filename) {
+        _cleanup_free_ char *path = NULL;
+        int r;
+
+        assert(j);
+        assert(prefix);
+        assert(filename);
+
+        if (j->no_new_files ||
+            !file_type_wanted(j->flags, filename))
+                return 0;
+
+        path = strjoin(prefix, "/", filename, NULL);
+        if (!path)
+                return -ENOMEM;
+
+        r = add_any_file(j, path);
+        if (r == -ENOENT)
+                return 0;
+        return 0;
+}
+
 static int remove_file(sd_journal *j, const char *prefix, const char *filename) {
         char *path;
         JournalFile *f;
@@ -1482,6 +1547,9 @@ static int add_root_directory(sd_journal *j, const char *p) {
                         inotify_rm_watch(j->inotify_fd, m->wd);
         }
 
+        if (j->no_new_files)
+                return 0;
+
         for (;;) {
                 struct dirent *de;
                 union dirent_storage buf;
@@ -1562,6 +1630,36 @@ static int add_search_paths(sd_journal *j) {
         return 0;
 }
 
+static int add_current_paths(sd_journal *j) {
+        Iterator i;
+        JournalFile *f;
+
+        assert(j);
+        assert(j->no_new_files);
+
+        /* Simply adds all directories for files we have open as
+         * "root" directories. We don't expect errors here, so we
+         * treat them as fatal. */
+
+        HASHMAP_FOREACH(f, j->files, i) {
+                int r;
+                _cleanup_free_ char *dir;
+
+                dir = dirname_malloc(f->path);
+                if (!dir)
+                        return -ENOMEM;
+
+                r = add_root_directory(j, dir);
+                if (r < 0) {
+                        set_put_error(j, r);
+                        return r;
+                }
+        }
+
+        return 0;
+}
+
+
 static int allocate_inotify(sd_journal *j) {
         assert(j);
 
@@ -1587,6 +1685,7 @@ static sd_journal *journal_new(int flags, const char *path) {
         if (!j)
                 return NULL;
 
+        j->original_pid = getpid();
         j->inotify_fd = -1;
         j->flags = flags;
         j->data_threshold = DEFAULT_DATA_THRESHOLD;
@@ -1619,7 +1718,8 @@ _public_ int sd_journal_open(sd_journal **ret, int flags) {
 
         if (flags & ~(SD_JOURNAL_LOCAL_ONLY|
                       SD_JOURNAL_RUNTIME_ONLY|
-                      SD_JOURNAL_SYSTEM_ONLY))
+                      SD_JOURNAL_SYSTEM|
+                      SD_JOURNAL_CURRENT_USER))
                 return -EINVAL;
 
         j = journal_new(flags, NULL);
@@ -1671,6 +1771,40 @@ fail:
         return r;
 }
 
+_public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int flags) {
+        sd_journal *j;
+        const char **path;
+        int r;
+
+        if (!ret)
+                return -EINVAL;
+
+        if (flags != 0)
+                return -EINVAL;
+
+        j = journal_new(flags, NULL);
+        if (!j)
+                return -ENOMEM;
+
+        STRV_FOREACH(path, paths) {
+                r = add_any_file(j, *path);
+                if (r < 0) {
+                        log_error("Failed to open %s: %s", *path, strerror(-r));
+                        goto fail;
+                }
+        }
+
+        j->no_new_files = true;
+
+        *ret = j;
+        return 0;
+
+fail:
+        sd_journal_close(j);
+
+        return r;
+}
+
 _public_ void sd_journal_close(sd_journal *j) {
         Directory *d;
         JournalFile *f;
@@ -1713,6 +1847,8 @@ _public_ int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret) {
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (!ret)
                 return -EINVAL;
 
@@ -1739,6 +1875,8 @@ _public_ int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id12
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         f = j->current_file;
         if (!f)
@@ -1805,6 +1943,8 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void **
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (!field)
                 return -EINVAL;
         if (!data)
@@ -1931,6 +2071,8 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (!data)
                 return -EINVAL;
         if (!size)
@@ -1981,6 +2123,8 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         if (j->inotify_fd >= 0)
                 return j->inotify_fd;
@@ -1991,7 +2135,9 @@ _public_ int sd_journal_get_fd(sd_journal *j) {
 
         /* Iterate through all dirs again, to add them to the
          * inotify */
-        if (j->path)
+        if (j->no_new_files)
+                r = add_current_paths(j);
+        else if (j->path)
                 r = add_root_directory(j, j->path);
         else
                 r = add_search_paths(j);
@@ -2006,6 +2152,8 @@ _public_ int sd_journal_get_events(sd_journal *j) {
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         fd = sd_journal_get_fd(j);
         if (fd < 0)
@@ -2019,6 +2167,8 @@ _public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (!timeout_usec)
                 return -EINVAL;
 
@@ -2119,6 +2269,8 @@ _public_ int sd_journal_process(sd_journal *j) {
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         j->last_process_usec = now(CLOCK_MONOTONIC);
 
@@ -2157,7 +2309,10 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
         int r;
         uint64_t t;
 
-        assert(j);
+        if (!j)
+                return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         if (j->inotify_fd < 0) {
 
@@ -2206,6 +2361,8 @@ _public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from,
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (!from && !to)
                 return -EINVAL;
         if (from == to)
@@ -2247,6 +2404,8 @@ _public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (!from && !to)
                 return -EINVAL;
         if (from == to)
@@ -2304,6 +2463,8 @@ _public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) {
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (!bytes)
                 return -EINVAL;
 
@@ -2325,6 +2486,8 @@ _public_ int sd_journal_query_unique(sd_journal *j, const char *field) {
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (isempty(field))
                 return -EINVAL;
         if (!field_is_valid(field))
@@ -2349,6 +2512,8 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (!data)
                 return -EINVAL;
         if (!l)
@@ -2461,6 +2626,8 @@ _public_ void sd_journal_restart_unique(sd_journal *j) {
 _public_ int sd_journal_reliable_fd(sd_journal *j) {
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         return !j->on_network;
 }
@@ -2494,6 +2661,8 @@ _public_ int sd_journal_get_catalog(sd_journal *j, char **ret) {
 
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (!ret)
                 return -EINVAL;
 
@@ -2531,6 +2700,8 @@ _public_ int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret) {
 _public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) {
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
 
         j->data_threshold = sz;
         return 0;
@@ -2539,6 +2710,8 @@ _public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) {
 _public_ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz) {
         if (!j)
                 return -EINVAL;
+        if (journal_pid_changed(j))
+                return -ECHILD;
         if (!sz)
                 return -EINVAL;