@@ -204,25 +204,26 @@ func (e RuntimeError) Unwrap() error {
204204 return e .Err
205205}
206206
207- // isFirstRun checks if this is the first time cagent is being run
208- // It creates a marker file in the user's config directory
207+ // isFirstRun checks if this is the first time cagent is being run.
208+ // It atomically creates a marker file in the user's config directory
209+ // using os.O_EXCL to avoid a race condition when multiple processes
210+ // start concurrently.
209211func isFirstRun () bool {
210212 configDir := paths .GetConfigDir ()
211213 markerFile := filepath .Join (configDir , ".cagent_first_run" )
212214
213- // Check if marker file exists
214- if _ , err := os .Stat (markerFile ); err == nil {
215- return false // File exists, not first run
216- }
217-
218- // Create marker file to indicate this run has happened
215+ // Ensure the config directory exists before trying to create the marker file
219216 if err := os .MkdirAll (configDir , 0o755 ); err != nil {
220- return false // Can't create config dir, assume not first run
217+ slog .Warn ("Failed to create config directory for first run marker" , "error" , err )
218+ return false
221219 }
222220
223- if err := os .WriteFile (markerFile , []byte ("" ), 0o644 ); err != nil {
224- return false // Can't create marker file, assume not first run
221+ // Atomically create the marker file. If it already exists, OpenFile returns an error.
222+ f , err := os .OpenFile (markerFile , os .O_RDWR | os .O_CREATE | os .O_EXCL , 0o644 )
223+ if err != nil {
224+ return false // File already exists or other error, not first run
225225 }
226+ f .Close ()
226227
227- return true // Successfully created marker, this is first run
228+ return true
228229}
0 commit comments