important_file_writer_cleaner.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_FILES_IMPORTANT_FILE_WRITER_CLEANER_H_
  5. #define BASE_FILES_IMPORTANT_FILE_WRITER_CLEANER_H_
  6. #include <atomic>
  7. #include <vector>
  8. #include "base/base_export.h"
  9. #include "base/containers/flat_set.h"
  10. #include "base/files/file_path.h"
  11. #include "base/memory/scoped_refptr.h"
  12. #include "base/no_destructor.h"
  13. #include "base/numerics/clamped_math.h"
  14. #include "base/sequence_checker.h"
  15. #include "base/synchronization/lock.h"
  16. #include "base/thread_annotations.h"
  17. #include "base/time/time.h"
  18. namespace base {
  19. class SequencedTaskRunner;
  20. // A cleaner for forgotten .tmp files left behind by ImportantFileWriter; see
  21. // https://crbug.com/1075917.
  22. //
  23. // ImportantFileWriter has the potential to leak .tmp files in case of a crash
  24. // or power failure during processing, or in case of interference by third-party
  25. // software. This class implements a singleton that makes a single scan over
  26. // given directories to delete any *.tmp files older than the current process.
  27. // Processes that use ImportantFileWriter are expected to call the instance's
  28. // Start method at some point during startup to enable the cleaner.
  29. // ImportantFileWriter calls the AddDirectory method to provide the directory
  30. // hosting an "important" file. Hosting processes are expected to call the Stop
  31. // method at shutdown.
  32. //
  33. // The deletion scan takes place in a background task.
  34. class BASE_EXPORT ImportantFileWriterCleaner {
  35. public:
  36. // Gets the process-wide single instance of the cleaner.
  37. static ImportantFileWriterCleaner& GetInstance();
  38. ImportantFileWriterCleaner(const ImportantFileWriterCleaner&) = delete;
  39. ImportantFileWriterCleaner& operator=(const ImportantFileWriterCleaner&) =
  40. delete;
  41. ~ImportantFileWriterCleaner() = delete;
  42. // Adds |directory| to the set to be cleaned if it has not already been
  43. // handled. If the Start method has already been called, the cleaner will
  44. // begin processing |directory| after all others that have previously been
  45. // added have been cleaned (immediately, if there are no others). Any calls to
  46. // this method prior to Initialize are ignored.
  47. static void AddDirectory(const FilePath& directory);
  48. // Initializes the instance on the hosting process's main sequence (the one on
  49. // which Start and Stop will ultimately be called). It is safe to call this
  50. // any number of times from the main sequence.
  51. void Initialize();
  52. // Starts the instance. If any directories have already been added, the
  53. // background task is posted immediately to begin processing them. Otherwise,
  54. // the next call to AddDirectory will begin processing.
  55. void Start();
  56. // Stops the instance. The background task, if it is active, is notified to
  57. // halt processing and return.
  58. void Stop();
  59. // Brings the instance back to the uninitialized state. This should be used in
  60. // tests that call Initialize so that the instance forgets about the test's
  61. // main thread task runner.
  62. void UninitializeForTesting();
  63. // Returns the upper-bound time. Files with modification times older than this
  64. // are assumed to have been orphaned by a previous instance of the process.
  65. base::Time GetUpperBoundTimeForTest() const;
  66. private:
  67. friend class NoDestructor<ImportantFileWriterCleaner>;
  68. ImportantFileWriterCleaner();
  69. // True once Start() has been called; false following Stop();
  70. bool is_started() const {
  71. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  72. return started_;
  73. }
  74. // True once the background task has been posted; false once it returns.
  75. bool is_running() const {
  76. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  77. return running_;
  78. }
  79. // The workhorse for AddDirectory.
  80. void AddDirectoryImpl(const FilePath& directory);
  81. // Schedules the background task to run, processing all directories that have
  82. // accumulated.
  83. void ScheduleTask();
  84. // Iterates over the contents of |directories|, deleting all *.tmp files older
  85. // than |upper_bound_time|. Checks |stop_flag| after each deletion to see if
  86. // the instance has been stopped by the host process. Returns false if
  87. // processing was interrupted by |stop_flag| having been set, or true
  88. // indicating that all directories were fully processed.
  89. static bool CleanInBackground(Time upper_bound_time,
  90. std::vector<FilePath> directories,
  91. std::atomic_bool& stop_flag);
  92. // Cleans up after completion of the background task. |processing_completed|
  93. // is true when all directories were fully processed, or false if the task
  94. // potentially exited early in response to Stop().
  95. void OnBackgroundTaskFinished(bool processing_completed);
  96. // Finalizes a request to stop after the background task returns.
  97. void DoStop();
  98. // Provides exclusive access to the instance's task runner.
  99. Lock task_runner_lock_;
  100. // The hosting process's main thread task runner.
  101. scoped_refptr<SequencedTaskRunner> task_runner_ GUARDED_BY(task_runner_lock_);
  102. // The time before which any discovered temporary file is presumed to be
  103. // unused, and therefore safe to delete.
  104. const Time upper_bound_time_;
  105. // The set of all directories hosting files written by an ImportantFileWriter.
  106. flat_set<FilePath> important_directories_
  107. GUARDED_BY_CONTEXT(sequence_checker_);
  108. // Directories added to the instance waiting either for a call to Start() or
  109. // waiting for an existing background task to complete.
  110. std::vector<FilePath> pending_directories_
  111. GUARDED_BY_CONTEXT(sequence_checker_);
  112. std::atomic_bool stop_flag_{false};
  113. bool started_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
  114. bool running_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
  115. SEQUENCE_CHECKER(sequence_checker_);
  116. };
  117. } // namespace base
  118. #endif // BASE_FILES_IMPORTANT_FILE_WRITER_CLEANER_H_