{
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());