@@ -364,22 +364,40 @@ module Server = struct
364364
365365 let socket_exists () = in_results_dir ~f: (fun () -> Sys. file_exists_exn socket_name)
366366
367- let server () =
368- L. debug Analysis Quiet " Sqlite write daemon: starting up@." ;
367+ (* Error recuperation is done by attempting this function at module initialization time, and
368+ not using DbWriter at all in case it fails. See {!can_use_socket} below. *)
369+ let setup_socket () =
369370 if socket_exists () then L. die InternalError " Sqlite write daemon: socket already exists@." ;
370371 let socket = Unix. socket ~domain: socket_domain ~kind: Unix. SOCK_STREAM ~protocol: 0 () in
371372 in_results_dir ~f: (fun () -> Unix. bind socket ~addr: socket_addr) ;
372373 (* [backlog] is (supposedly) the length of the queue for pending connections ;
373374 there are no rules about the implied behaviour though. Here use optimistically
374375 the number of workers, though even that is a guess. *)
375376 Unix. listen socket ~backlog: Config. jobs ;
377+ socket
378+
379+
380+ let remove_socket socket =
381+ in_results_dir ~f: (fun () ->
382+ Unix. close socket ;
383+ Unix. unlink socket_name )
384+
385+
386+ (* Check whether we can create a socket to communicate with the asynchronous DBWriter process. *)
387+ let can_use_socket () =
388+ try
389+ let socket = setup_socket () in
390+ remove_socket socket ;
391+ true
392+ with _ -> false
393+
394+
395+ let server () =
396+ L. debug Analysis Quiet " Sqlite write daemon: starting up@." ;
397+ let socket = setup_socket () in
376398 L. debug Analysis Quiet " Sqlite write daemon: set up complete, waiting for connections@." ;
377- let shutdown () =
378- in_results_dir ~f: (fun () ->
379- Unix. close socket ;
380- Unix. remove socket_name )
381- in
382- Exception. try_finally ~f: (fun () -> server_loop socket) ~finally: shutdown
399+ let finally () = remove_socket socket in
400+ Exception. try_finally ~f: (fun () -> server_loop socket) ~finally
383401
384402
385403 let send cmd =
@@ -420,15 +438,30 @@ module Server = struct
420438end
421439
422440let use_daemon =
423- let is_windows = match Version. build_platform with Windows -> true | Linux | Darwin -> false in
424- Config. ((not is_windows) && dbwriter && (not (buck || genrule_mode)) && jobs > 1 )
425-
426-
427- let perform cmd = if use_daemon then Server. send cmd else Command. execute cmd
441+ lazy
442+ (let is_windows =
443+ match Version. build_platform with Windows -> true | Linux | Darwin -> false
444+ in
445+ Config. ((not is_windows) && dbwriter && (not (buck || genrule_mode)) && jobs > 1 )
446+ &&
447+ (* Only the main process should try detecting whether the socket can be created.
448+ Otherwise, re-spawned Infer will try to create a socket on top of the existing one. *)
449+ if Config. is_originator then (
450+ let socket_ok = Server. can_use_socket () in
451+ if not socket_ok then
452+ L. user_warning
453+ " Cannot setup the socket to communicate with the database daemon. Performance will be \
454+ impacted. Do you have enough rights to create a Unix socket in directory '%s'?@."
455+ Config. toplevel_results_dir ;
456+ socket_ok )
457+ else Server. socket_exists () )
458+
459+
460+ let perform cmd = if Lazy. force use_daemon then Server. send cmd else Command. execute cmd
428461
429462let start () = Server. start ()
430463
431- let stop () = Server. send Command. Terminate
464+ let stop () = try Server. send Command. Terminate with Unix. Unix_error _ -> ()
432465
433466let replace_attributes ~proc_uid ~proc_name ~attr_kind ~source_file ~proc_attributes ~cfg ~callees =
434467 perform
0 commit comments