sessiond: make subsession remove user operation atomic 57/286557/3 accepted/tizen/unified/20230117.140453
authorAdam Michalski <a.michalski2@partner.samsung.com>
Mon, 9 Jan 2023 16:51:31 +0000 (17:51 +0100)
committerAdam Michalski <a.michalski2@partner.samsung.com>
Tue, 10 Jan 2023 15:34:41 +0000 (16:34 +0100)
Change-Id: I04d6d76062edf4e7de955a2f34cb40ee59ffc123

src/service/src/fs_helpers.cpp

index c052b826a77ebc7b25061206702425ab5aeb0d67..64125ff3cbacb3e906cf925afaf4fdc2177412fc 100644 (file)
@@ -390,15 +390,30 @@ void remove_user_subsession(const int session_uid, const std::string_view subses
 {
        try {
                std::string home_dir = get_home_dir_by_user_id(session_uid);
-               fs::path subsession_path {
-                       std::move(home_dir) + "/" + main_dir_name.data() + "/" + subsession_id.data()
-               };
+               std::string main_dir = std::move(home_dir) + "/" + main_dir_name.data();
 
+               std::string subsession_dir = main_dir + "/" + subsession_id.data();
+               const fs::path subsession_path { std::move(subsession_dir) };
                if (!fs::exists(subsession_path))
                        throw std::system_error(ENOENT, std::generic_category(),
                                "Subsession directory does not exist");
 
-               fs::remove_all(subsession_path);
+               /* We are going to rename the subsession dir before deleting it,
+                * because that makes the removal appear atomic. The temporary
+                * name is different than the one for adding a subsession to avoid
+                * a possible collision with `add_user_subsession` which also uses
+                * a temporary dir. */
+               std::string tmp_subsession_dir = std::move(main_dir) + "/.tmpremove" + subsession_id.data();
+               const fs::path tmp_subsession_path { std::move(tmp_subsession_dir) };
+
+               /* Ensure that any possible residue from previously
+                * failed subsession deletion is cleaned up. */
+               if (fs::exists(tmp_subsession_path))
+                       fs::remove_all(tmp_subsession_path);
+
+               /* Perform the rename-and-delete. */
+               fs::rename(subsession_path, tmp_subsession_path);
+               fs::remove_all(tmp_subsession_path);
        }
        catch (std::system_error const &ex) {
                LOGE("Logic exception %s\nwhile removing user subsession data [session_uid=%d subsession_id=%s]", ex.what(), session_uid, subsession_id.data());