]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sleep,home: always initialize UnitFreezer if used 33092/head
authorMike Yuan <me@yhndnzj.com>
Tue, 11 Jun 2024 14:00:22 +0000 (16:00 +0200)
committerMike Yuan <me@yhndnzj.com>
Wed, 17 Jul 2024 16:14:33 +0000 (18:14 +0200)
Previously, unit_freezer_new_freeze() would only return
UnitFreezer object if FreezeUnit() succeeds. This is not
ideal though, as a failed bus call doesn't mean the action
actually failed. E.g. a timeout might occur because pid1
is waiting for cgroup event from kernel, while the bus call
timeout was exceeded (#33269). In such a case, ThawUnit()
will never be called, resulting in frozen units remain that
way after resuming from sleep.

Therefore, let's get rid of unit_freezer_new_freeze(),
and make sure as long as unit freezer is involved, we'll
call ThawUnit() when we're done. This should make things
a lot more robust.

src/home/homework.c
src/shared/bus-unit-util.c
src/shared/bus-unit-util.h
src/sleep/sleep.c

index 2537e8d1ddd11e31deb89791cd792421b386a882..00e74894b32849e4dc78a308131961b0fe5b4c52 100644 (file)
@@ -1870,7 +1870,7 @@ static int home_inspect(UserRecord *h, UserRecord **ret_home) {
         return 1;
 }
 
-static int user_session_freezer(uid_t uid, bool freeze_now, UnitFreezer **ret) {
+static int user_session_freezer_new(uid_t uid, UnitFreezer **ret) {
         _cleanup_free_ char *unit = NULL;
         int r;
 
@@ -1881,10 +1881,6 @@ static int user_session_freezer(uid_t uid, bool freeze_now, UnitFreezer **ret) {
         if (r < 0 && r != -ENXIO)
                 log_warning_errno(r, "Cannot parse value of $SYSTEMD_HOME_LOCK_FREEZE_SESSION, ignoring: %m");
         else if (r == 0) {
-                if (freeze_now)
-                        log_notice("Session remains unfrozen on explicit request ($SYSTEMD_HOME_LOCK_FREEZE_SESSION=0).\n"
-                                   "This is not recommended, and might result in unexpected behavior including data loss!");
-
                 *ret = NULL;
                 return 0;
         }
@@ -1892,10 +1888,7 @@ static int user_session_freezer(uid_t uid, bool freeze_now, UnitFreezer **ret) {
         if (asprintf(&unit, "user-" UID_FMT ".slice", uid) < 0)
                 return log_oom();
 
-        if (freeze_now)
-                r = unit_freezer_new_freeze(unit, ret);
-        else
-                r = unit_freezer_new(unit, ret);
+        r = unit_freezer_new(unit, ret);
         if (r < 0)
                 return r;
 
@@ -1921,9 +1914,16 @@ static int home_lock(UserRecord *h) {
 
         _cleanup_(unit_freezer_freep) UnitFreezer *f = NULL;
 
-        r = user_session_freezer(h->uid, /* freeze_now= */ true, &f);
+        r = user_session_freezer_new(h->uid, &f);
         if (r < 0)
                 return r;
+        if (r > 0) {
+                r = unit_freezer_freeze(f);
+                if (r < 0)
+                        return r;
+        } else
+                log_notice("Session remains unfrozen on explicit request ($SYSTEMD_HOME_LOCK_FREEZE_SESSION=0).\n"
+                           "This is not recommended, and might result in unexpected behavior including data loss!");
 
         r = home_lock_luks(h, &setup);
         if (r < 0) {
@@ -1966,7 +1966,7 @@ static int home_unlock(UserRecord *h) {
         _cleanup_(unit_freezer_freep) UnitFreezer *f = NULL;
 
         /* We want to thaw the session only after it's safe to access $HOME */
-        r = user_session_freezer(h->uid, /* freeze_now= */ false, &f);
+        r = user_session_freezer_new(h->uid, &f);
         if (r > 0)
                 r = unit_freezer_thaw(f);
         if (r < 0)
index 751cb29c62498849d07581a95fdc876732f3d0d8..259fbeaf5c4f52307211835cd2561fb152cff98c 100644 (file)
@@ -3025,22 +3025,3 @@ int unit_freezer_freeze(UnitFreezer *f) {
 int unit_freezer_thaw(UnitFreezer *f) {
         return unit_freezer_action(f, false);
 }
-
-int unit_freezer_new_freeze(const char *name, UnitFreezer **ret) {
-        _cleanup_(unit_freezer_freep) UnitFreezer *f = NULL;
-        int r;
-
-        assert(name);
-        assert(ret);
-
-        r = unit_freezer_new(name, &f);
-        if (r < 0)
-                return r;
-
-        r = unit_freezer_freeze(f);
-        if (r < 0)
-                return r;
-
-        *ret = TAKE_PTR(f);
-        return 0;
-}
index ea4056c6910465fc1b5ec726384740662aa11bea..6f0d55971ce3ccdd101ea98c0e2ed6ac3ddbaabc 100644 (file)
@@ -45,5 +45,3 @@ int unit_freezer_new(const char *name, UnitFreezer **ret);
 
 int unit_freezer_freeze(UnitFreezer *f);
 int unit_freezer_thaw(UnitFreezer *f);
-
-int unit_freezer_new_freeze(const char *name, UnitFreezer **ret);
index 7e5075a63cb9cd454ce094fa76b679e8673b5806..15ef7ae9131842de8fd4906f52876cd2f6b2618f 100644 (file)
@@ -604,9 +604,13 @@ static int run(int argc, char *argv[]) {
         r = getenv_bool("SYSTEMD_SLEEP_FREEZE_USER_SESSIONS");
         if (r < 0 && r != -ENXIO)
                 log_warning_errno(r, "Cannot parse value of $SYSTEMD_SLEEP_FREEZE_USER_SESSIONS, ignoring: %m");
-        if (r != 0)
-                (void) unit_freezer_new_freeze(SPECIAL_USER_SLICE, &user_slice_freezer);
-        else
+        if (r != 0) {
+                r = unit_freezer_new(SPECIAL_USER_SLICE, &user_slice_freezer);
+                if (r < 0)
+                        return r;
+
+                (void) unit_freezer_freeze(user_slice_freezer);
+        } else
                 log_notice("User sessions remain unfrozen on explicit request ($SYSTEMD_SLEEP_FREEZE_USER_SESSIONS=0).\n"
                            "This is not recommended, and might result in unexpected behavior, particularly\n"
                            "in suspend-then-hibernate operations or setups with encrypted home directories.");