From 3f6af9a26a91e2ff4855f5b4aceadffc0c7dca7e Mon Sep 17 00:00:00 2001 From: inglorion Date: Wed, 16 Dec 2009 21:55:20 +0100 Subject: [PATCH] Added various log messages to mailvisad. --- src/mailvisad.ml | 226 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 133 insertions(+), 93 deletions(-) diff --git a/src/mailvisad.ml b/src/mailvisad.ml index 6258721..3b8160e 100644 --- a/src/mailvisad.ml +++ b/src/mailvisad.ml @@ -92,97 +92,137 @@ let _ = (* Open logfile. *) set_log_channel (open_out_gen [Open_wronly; Open_append; Open_creat; Open_text] 0o600 logfile); - (* Open socket. *) - let sock = socket PF_UNIX SOCK_STREAM 0 in - let sockaddr = (ADDR_UNIX sockpath) in - let _ = - (try - bind sock sockaddr; - with Unix_error(code,_,_) -> - if code = EADDRINUSE then begin - (* Address already in use - test if socket is really active. *) - (* If we can connect to the address, assume mailvisad is already running. *) - try - let conn = socket PF_UNIX SOCK_STREAM 0 in - connect conn sockaddr; - close conn; - output_string Pervasives.stderr ("mailvisad already bound to " ^ sockpath ^ "\n"); - exit 0 - with Unix_error _ -> - (* Couldn't connect. If sockpath is a socket, remove it and try binding again. *) - unlink_if_socket sockpath; - try bind sock sockaddr - with Unix_error (code,_,_) -> - output_string Pervasives.stderr ((error_message code) ^ "\n"); - exit 1 - end); - listen sock 3; - - (* Fork and exit parent. *) - if (fork ()) != 0 then exit 0; - - (* Set at_exit handler to close and remove socket and pidfile. *) - at_exit (fun _ -> - close sock; - unlink_if_socket sockpath; - unlink pidfile); - - (* Install SIGTERM handler to gracefully exit program. *) - set_signal sigterm (Signal_handle (fun _ -> exit 0)); - - (* Install SIGCHLD handler to collect exited child processes. *) - set_signal sigchld (Signal_handle (fun _ -> - (* Keep calling waitpid until there are no more - processes to collect. *) - let rec collect _ = - try - let pid, _ = waitpid [WNOHANG] (-1) in - if pid != -1 then collect () - with _ -> () - in collect ())); - - (* Detach process from terminal. *) - close stdin; - ignore (setsid ()); - - (* Write pid file. *) - let pid_channel = open_out pidfile in - output_string pid_channel ((string_of_int (getpid ())) ^ "\n"); - close_out pid_channel - in - - (* Load scores. *) - let scores = load_wordlist scorefile in - (* Main loop. - Accept a connection on the socket, read the first so many bytes of the message, - extract the most interesting words, compute spam probability, and - send result out over the connection. - *) - while true do - let connection, address = accept sock in - (* Handle connection in new child process. *) - try - (* - let pid = fork () in - if pid = 0 then - (* Child process; handle connection. *) - *) - begin - (try - let message = sock_recv connection 16384 in - let probability = spam_probability (extract_interesting_words message scores) scores in - sock_send connection (string_of_float probability); - close connection; - with exn -> - close connection; - raise exn); - (* exit 0; *) - end - (* - else + (* Set loglevel. *) + set_loglevel loglevel_notice; + + (* Wrap the whole rest of the program with exception handlers that + * log errors. *) + Printexc.record_backtrace true; + try + log_notice "Starting up"; + + (* Open socket. *) + let sock = socket PF_UNIX SOCK_STREAM 0 in + let sockaddr = (ADDR_UNIX sockpath) in + let _ = + (try + log_debug "Creating socket"; + bind sock sockaddr + with Unix_error(code,_,_) -> + if code = EADDRINUSE then begin + log_debug "Address already in use"; + (* Address already in use - test if socket is really active. *) + (* If we can connect to the address, assume mailvisad is already running. *) + try + let conn = socket PF_UNIX SOCK_STREAM 0 in + connect conn sockaddr; + close conn; + let msg = ("mailvisad already bound to " ^ sockpath ^ ", exiting\n") + in + log_notice msg; + prerr_endline msg; + exit 0 + with Unix_error _ -> + (* Couldn't connect. If sockpath is a socket, remove it and try binding again. *) + unlink_if_socket sockpath; + log_debug "Removed socket file, trying to bind again"; + try bind sock sockaddr + with Unix_error (code,_,_) -> + log_fatal (error_message code); + exit 1 + end); + log_debug "Successfully created socket"; + listen sock 3; + + (* Fork and exit parent. *) + if (fork ()) != 0 then exit 0; + + (* Set at_exit handler to close and remove socket and pidfile. *) + at_exit (fun _ -> + log_notice "Exiting"; + close sock; + unlink_if_socket sockpath; + unlink pidfile); + + (* Install SIGTERM handler to gracefully exit program. *) + set_signal sigterm (Signal_handle (fun _ -> + log_notice "Got SIGTERM"; + exit 0)); + + (* Install SIGCHLD handler to collect exited child processes. *) + set_signal sigchld (Signal_handle (fun _ -> + (* Keep calling waitpid until there are no more + processes to collect. *) + let rec collect _ = + try + let pid, _ = waitpid [WNOHANG] (-1) in + if pid != -1 then collect () + with _ -> () + in collect ())); + + (* Detach process from terminal. *) + close stdin; + ignore (setsid ()); + + (* Write pid file. *) + let pid_channel = open_out pidfile in + output_string pid_channel ((string_of_int (getpid ())) ^ "\n"); + close_out pid_channel + in + + (* Load scores. *) + log_debug "Loading scores"; + let scores = load_wordlist scorefile in + log_debug "Scores loaded"; + (* Main loop. + Accept a connection on the socket, read the first so many bytes of the message, + extract the most interesting words, compute spam probability, and + send result out over the connection. + *) + while true do + log_debug "Ready for new connection"; + let connection, address = accept sock in + log_debug "Received new connection"; + (* Handle connection in new child process. *) + try + (* + let pid = fork () in + if pid = 0 then + (* Child process; handle connection. *) + *) + begin + (try + let message = sock_recv connection 16384 in + if (String.length message) == 0 then + (* Empty message; ignore. *) + log_debug "Ignoring empty message" + else begin + let probability = spam_probability (extract_interesting_words message scores) scores in + let prob_str = string_of_float probability in + log_debug ("Spam probability: " ^ prob_str); + sock_send connection prob_str; + end; + log_debug "Closing connection"; + close connection + with exn -> + log_error ((Printexc.to_string exn) ^ + "\n" ^ + (Printexc.get_backtrace ())); + close connection; + raise exn); + (* exit 0; *) + end + (* + else (* Parent process; close connection. *) - close connection - *) - with Unix_error (code,_,_) -> - output_string Pervasives.stderr ((error_message code) ^ "\n") - done + close connection + *) + with Unix_error (code,_,_) -> + log_error (error_message code) + done + with + | exn -> + log_fatal ((Printexc.to_string exn) ^ + "\n" ^ + (Printexc.get_backtrace ())); + exit 1 -- 2.11.4.GIT