2 ** Copyright 2001 Addison Wesley. All Rights Reserved.
5 #include "ace/Log_Msg.h"
6 #include "ace/Process_Manager.h"
7 #include "ace/Signal.h"
8 #include "ace/OS_NS_string.h"
9 #include "ace/os_include/os_fcntl.h"
11 #include "Process_Per_Connection_Logging_Server.h"
12 #include "Logging_Handler.h"
17 extern "C" void sigterm_handler (int /* signum */) { /* No-op. */ }
21 Logging_Process::Logging_Process (const char *prog_name
,
22 const ACE_SOCK_Stream
&logging_peer
)
23 : logging_peer_ (logging_peer
.get_handle ())
25 ACE_OS::strcpy (prog_name_
, prog_name
);
28 // Set up the process options here. If the decision to do a fork
29 // a no exec on POSIX needs to be changed, this is the only place
30 // that needs to change (omit the creation_flags() call).
31 // We request that the logging client's socket handle be passed
32 // to the child process. The internals of ACE_Process insure that
33 // it gets put on the command line if starting a new program image,
34 // and that if it needed to be duplicated to accomplish that (such
35 // as on Win32) it will get properly closed.
36 // The process_name () call sets the program to run and is also used
37 // for the fork() call on POSIX.
38 // avoid_zombies has a real affect only on POSIX; it's harmless on Win32.
39 // Setting the NO_EXEC creation flag is what prevents the exec() on
40 // POSIX. It has no affect on Win32.
42 Logging_Process::prepare (ACE_Process_Options
&options
)
44 if (options
.pass_handle (logging_peer_
.get_handle ()) == -1)
45 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n", "pass_handle"), -1);
46 options
.command_line ("%s", prog_name_
);
47 options
.avoid_zombies (1);
48 options
.creation_flags (ACE_Process_Options::NO_EXEC
);
52 // Just delete the process object. If any handles needed to be
53 // duplicated to be passed to the child, they'll get closed now
54 // by the ACE_Process destructor.
56 Logging_Process::unmanage ()
63 Process_Per_Connection_Logging_Server::handle_connections ()
65 ACE_SOCK_Stream logging_peer
;
67 // Block until a client connects.
68 if (acceptor ().accept (logging_peer
) == -1)
71 Logging_Process
*logger
=
72 new Logging_Process (prog_name_
, logging_peer
);
73 ACE_Process_Options options
;
75 pid
= ACE_Process_Manager::instance ()->spawn (logger
,
77 // If we came back with pid 0 from the spawn(), this is a
78 // POSIX fork system - we are in the child process. Handle the
79 // logging records, then exit.
82 handle_data (&logging_peer
);
86 logging_peer
.close ();
88 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n", "spawn()"), -1);
90 // See if there are any child processes that have
91 // exited - reap their status and clean up handles held
92 // open while the child executed.
93 ACE_Process_Manager::instance ()->wait (0,
94 ACE_Time_Value::zero
);
99 Process_Per_Connection_Logging_Server::handle_data (ACE_SOCK_Stream
*client
)
101 // Disable non-blocking mode.
102 client
->disable (ACE_NONBLOCK
);
103 ACE_FILE_IO log_file
;
104 make_log_file (log_file
, client
);
105 Logging_Handler
logging_handler (log_file
, *client
);
107 while (logging_handler
.log_record () != -1)
116 Process_Per_Connection_Logging_Server::run (int argc
, char *argv
[])
118 ACE_OS::strncpy (prog_name_
, argv
[0], MAXPATHLEN
);
119 prog_name_
[MAXPATHLEN
] = '\0'; // Ensure NUL-termination.
120 // If there are 2 command line arguments after prog_name_, this
121 // is a spawned worker process. Else run as the master.
123 return run_worker (argc
, argv
); // Only on Win32.
125 return run_master (argc
, argv
);
129 Process_Per_Connection_Logging_Server::run_master (int argc
, char *argv
[])
131 u_short logger_port
= 0;
133 logger_port
= ACE_OS::atoi (argv
[1]);
134 if (this->open (logger_port
) == -1)
138 if (handle_connections () == -1)
141 ACE_NOTREACHED (return 0;)
145 Process_Per_Connection_Logging_Server::run_worker (int, char *argv
[])
147 // The handle value is passed as a hex pointer value on Windows and a
148 // decimal number everywhere else. See ace/Process.cpp for info.
149 #if defined (ACE_WIN32)
150 intptr_t client_handle_i
= 0;
151 # if defined (ACE_WIN64)
152 const char *fmt
= "%I64x";
154 const char *fmt
= "%x";
155 # endif /* ACE_WIN64 */
156 # if defined (ACE_HAS_TR24731_2005_CRT)
157 if (::sscanf_s (argv
[2], fmt
, &client_handle_i
) == 0)
160 if (::sscanf (argv
[2], fmt
, &client_handle_i
) == 0)
162 # endif /* ACE_HAS_TR24731_2005_CRT */
163 ACE_HANDLE client_handle
=
164 reinterpret_cast<ACE_HANDLE
> (client_handle_i
);
166 ACE_HANDLE client_handle
= static_cast<ACE_HANDLE
> (ACE_OS::atoi (argv
[2]));
167 #endif /* ACE_WIN32 */
168 ACE_SOCK_Stream
client (client_handle
);
170 handle_data (&client
);
176 int ACE_TMAIN (int argc
, ACE_TCHAR
*argv
[])
178 // Register to receive the <SIGTERM> signal.
179 ACE_Sig_Action
sa ((ACE_SignalHandler
)sigterm_handler
,
182 Process_Per_Connection_Logging_Server server
;
184 if (server
.run (argc
, argv
) == -1 && errno
!= EINTR
)
185 ACE_ERROR_RETURN ((LM_ERROR
, "%p\n", "server.run()"), 1);
187 // Barrier synchronization.
188 return ACE_Process_Manager::instance ()->wait ();