@@ -19,8 +19,6 @@ open Printf
1919module D = Debug. Make (struct let name= " v6daemon" end )
2020open D
2121
22- module W = Debug. Make (struct let name= " watchdog" end )
23-
2422let xmlrpc_handler process req bio _ =
2523 Debug. with_thread_associated " v6d_handler" (fun () ->
2624 let path = match String. split '/' req.Http.Request. uri with
@@ -43,149 +41,18 @@ let xmlrpc_handler process req bio _ =
4341
4442let server = Http_svr.Server. empty ()
4543
46- let daemon_init post_daemonize_hook process =
44+ let startup process =
4745 Debug. with_thread_associated " daemon_init" (fun () ->
48- post_daemonize_hook () ;
49-
46+ info " (Re)starting v6d..." ;
5047 (* unix socket *)
5148 let unix_socket_path = Filename. concat " /var/lib/xcp" " v6" in
5249 Stdext.Unixext. mkdir_safe (Filename. dirname unix_socket_path) 0o700 ;
5350 Stdext.Unixext. unlink_safe unix_socket_path;
5451 let domain_sock = Http_svr. bind (Unix. ADDR_UNIX (unix_socket_path)) " unix_rpc" in
5552 Http_svr. start server domain_sock;
5653 Http_svr.Server. add_handler server Http. Post " /" (Http_svr. BufIO (xmlrpc_handler process));
57-
58- (* TCP socket: only use for testing! *)
59- (* let localhost = Unix.inet_addr_of_string "127.0.0.1" in
60- let localhost_sock = Http_svr.bind (Unix.ADDR_INET(localhost, 4094)) in
61- ignore(Http_svr.start (localhost_sock, "inet-RPC"));*)
62-
54+ ignore Daemon. (notify State. Ready );
6355 (* keep daemon alive *)
6456 Stdext.Threadext. keep_alive ()
6557 ) ()
6658
67- let watchdog f =
68- Debug. with_thread_associated " watchdog" (fun () ->
69- (* parent process blocks sigint and forward sigterm to child. *)
70- ignore(Unix. sigprocmask Unix. SIG_BLOCK [Sys. sigint]);
71- Sys. catch_break false ;
72-
73- (* watchdog logic *)
74- let loginfo fmt = W. info fmt in
75-
76- let restart = ref true
77- and error_msg = ref " " and exit_code = ref 0
78- and last_badsig = ref (0. ) and pid = ref 0
79- and last_badexit = ref (0. ) and no_retry_interval = 10. in
80-
81- while ! restart
82- do
83- begin
84- loginfo " (Re)starting v6d..." ;
85- if ! pid = 0 then
86- begin
87- let newpid = Unix. fork () in
88- if newpid = 0 then
89- begin
90- try
91- ignore(Unix. sigprocmask Unix. SIG_UNBLOCK [Sys. sigint]);
92- f () ;
93- exit 127
94- with e ->
95- error " Caught exception at toplevel: '%s'" (Printexc. to_string e);
96- Debug. log_backtrace e (Backtrace. get e);
97- raise e (* will exit the process with rc=2 *)
98- end ;
99- (* parent just reset the sighandler *)
100- Sys. set_signal Sys. sigterm (Sys. Signal_handle (fun i ->
101- restart := false ; Unix. kill newpid Sys. sigterm));
102- pid := newpid
103- end ;
104- try
105- (* remove the pid in all case, except stop *)
106- match snd (Unix. waitpid [] ! pid) with
107- | Unix. WEXITED 0 ->
108- loginfo " Received exit code 0. Not restarting." ;
109- pid := 0 ;
110- restart := false ;
111- error_msg := " " ;
112- | Unix. WEXITED i ->
113- loginfo " Received exit code %d" i;
114- exit_code := i;
115- pid := 0 ;
116- let ctime = Unix. time () in
117- if ctime < (! last_badexit +. no_retry_interval) then
118- begin
119- restart := false ;
120- loginfo " Received 2 bad exits within no-retry-interval. Giving up." ;
121- end
122- else
123- begin
124- (* restart := true; -- don't need to do this - it's true already *)
125- loginfo " Received bad exit, retrying" ;
126- last_badexit := ctime
127- end
128- | Unix. WSIGNALED i ->
129- loginfo " Received signal %s" (Stdext.Unixext. string_of_signal i);
130- pid := 0 ;
131- (* arbitrary choice of signals, probably need more though, for real use *)
132- if i = Sys. sigsegv || i = Sys. sigpipe then
133- begin
134- let ctime = Unix. time () in
135- if ctime < (! last_badsig +. no_retry_interval) then
136- begin
137- restart := false ;
138- error_msg := sprintf " v6d died with signal %d: not restarting (2 bad signals within no_retry_interval)" i;
139- exit_code := 13
140- end
141- else
142- begin
143- loginfo " v6d died with signal %d: restarting" i;
144- last_badsig := ctime
145- end
146- end
147- else
148- begin
149- restart := false ;
150- error_msg := sprintf " v6d died with signal %d: not restarting (watchdog never restarts on this signal)" i;
151- exit_code := 12
152- end
153- | Unix. WSTOPPED i ->
154- loginfo " Receive stop code %i" i;
155- Unix. sleep 1 ;
156- (* well, just resume the stop process. the watchdog cannot do anything if the process is stopped *)
157- Unix. kill ! pid Sys. sigcont;
158- with
159- | Unix. Unix_error (Unix. EINTR,_ ,_ ) -> ()
160- | e -> loginfo " Watchdog received unexpected exception: %s" (Printexc. to_string e)
161- end ;
162- done ;
163- if ! error_msg <> " " then
164- begin
165- loginfo " v6d watchdog exiting." ;
166- loginfo " Fatal: %s" ! error_msg;
167- eprintf " %s\n " ! error_msg;
168- end ;
169- exit ! exit_code
170- ) ()
171-
172-
173- let daemon = ref false
174- let pidfile = ref " "
175-
176- (* A lot of this boilerplate ought to go into a utility library *)
177- let startup post_daemonize_hook process =
178- (* Parse command-line arguments *)
179- Arg. parse [ " -daemon" , Arg. Set daemon, " Daemonize" ;
180- " -pidfile" , Arg. Set_string pidfile, " pidfile" ]
181- (fun x -> warn " Ignoring argument: %s" x)
182- " v6 licensing daemon" ;
183-
184- if ! daemon then
185- Stdext.Unixext. daemonize () ;
186-
187- if ! pidfile <> " " then
188- Stdext.Unixext. pidfile_write ! pidfile;
189-
190- watchdog (fun () -> daemon_init post_daemonize_hook process)
191-
0 commit comments