33//! It implements the basic functionality of parsing the command line arguments and either
44//! performing one-shot actions or starting the main agent control process.
55#![ warn( missing_docs) ]
6-
76use newrelic_agent_control:: agent_control:: run:: on_host:: AGENT_CONTROL_MODE_ON_HOST ;
87use newrelic_agent_control:: agent_control:: run:: { AgentControlRunConfig , AgentControlRunner } ;
98use newrelic_agent_control:: command:: Command ;
@@ -16,8 +15,38 @@ use std::error::Error;
1615use std:: process:: ExitCode ;
1716use tracing:: { error, info, trace} ;
1817
18+ #[ cfg( target_os = "windows" ) ]
19+ use newrelic_agent_control:: command:: windows:: { WINDOWS_SERVICE_NAME , setup_windows_service} ;
20+
21+ #[ cfg( target_os = "windows" ) ]
22+ windows_service:: define_windows_service!( ffi_service_main, service_main) ;
23+
1924fn main ( ) -> ExitCode {
20- Command :: run ( AGENT_CONTROL_MODE_ON_HOST , _main)
25+ #[ cfg( target_family = "unix" ) ]
26+ {
27+ Command :: run ( AGENT_CONTROL_MODE_ON_HOST , _main)
28+ }
29+
30+ #[ cfg( target_os = "windows" ) ]
31+ {
32+ if windows_service:: service_dispatcher:: start ( WINDOWS_SERVICE_NAME , ffi_service_main)
33+ . is_err ( )
34+ {
35+ // Not running as Windows Service, run normally
36+ return Command :: run ( AGENT_CONTROL_MODE_ON_HOST , |cfg, tracer| {
37+ _main ( cfg, tracer, false )
38+ } ) ;
39+ }
40+ ExitCode :: SUCCESS
41+ }
42+ }
43+
44+ #[ cfg( target_os = "windows" ) ]
45+ /// Entry-point for Windows Service
46+ fn service_main ( _arguments : Vec < std:: ffi:: OsString > ) {
47+ let _ = Command :: run ( AGENT_CONTROL_MODE_ON_HOST , |cfg, tracer| {
48+ _main ( cfg, tracer, true )
49+ } ) ;
2150}
2251
2352/// This is the actual main function.
@@ -33,6 +62,7 @@ fn main() -> ExitCode {
3362fn _main (
3463 agent_control_run_config : AgentControlRunConfig ,
3564 _tracer : Vec < TracingGuardBox > , // Needs to take ownership of the tracer as it can be shutdown on drop
65+ #[ cfg( target_os = "windows" ) ] as_windows_service : bool ,
3666) -> Result < ( ) , Box < dyn Error > > {
3767 #[ cfg( not( feature = "disable-asroot" ) ) ]
3868 if !is_elevated ( ) ? {
@@ -52,12 +82,22 @@ fn _main(
5282 let ( application_event_publisher, application_event_consumer) = pub_sub ( ) ;
5383
5484 trace ! ( "creating the signal handler" ) ;
55- create_shutdown_signal_handler ( application_event_publisher) ?;
85+ create_shutdown_signal_handler ( application_event_publisher. clone ( ) ) ?;
86+
87+ #[ cfg( target_os = "windows" ) ]
88+ let tear_down_windows_service = as_windows_service
89+ . then ( || setup_windows_service ( application_event_publisher) )
90+ . transpose ( ) ?;
5691
5792 // Create the actual agent control runner with the rest of required configs and the application_event_consumer
5893 AgentControlRunner :: new ( agent_control_run_config, application_event_consumer) ?. run ( ) ?;
5994
60- info ! ( "exiting gracefully" ) ;
95+ #[ cfg( target_os = "windows" ) ]
96+ if let Some ( tear_down_fn) = tear_down_windows_service {
97+ tear_down_fn ( ) ?;
98+ }
99+
100+ info ! ( "Exiting gracefully" ) ;
61101
62102 Ok ( ( ) )
63103}
0 commit comments