diff options
Diffstat (limited to 'winsup/cygwin/cygserver.cc')
-rwxr-xr-x | winsup/cygwin/cygserver.cc | 228 |
1 files changed, 102 insertions, 126 deletions
diff --git a/winsup/cygwin/cygserver.cc b/winsup/cygwin/cygserver.cc index 32e93dc47c8..9baf9030395 100755 --- a/winsup/cygwin/cygserver.cc +++ b/winsup/cygwin/cygserver.cc @@ -12,14 +12,12 @@ details. */ #include "woutsup.h" -#include <sys/socket.h> #include <sys/types.h> #include <assert.h> #include <ctype.h> #include <errno.h> #include <getopt.h> -#include <netdb.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> @@ -35,10 +33,6 @@ details. */ #include "cygwin/cygserver_process.h" #include "cygwin/cygserver_transport.h" -GENERIC_MAPPING access_mapping; - -DWORD request_count = 0; - // Version string. static const char version[] = "$Revision$"; @@ -127,6 +121,8 @@ __set_errno (const char *func, int ln, int val) #endif /* DEBUGGING */ +GENERIC_MAPPING access_mapping; + static BOOL setup_privileges () { @@ -257,7 +253,7 @@ check_and_dup_handle (HANDLE from_process, HANDLE to_process, */ void -client_request_attach_tty::serve (transport_layer_base * const conn, +client_request_attach_tty::serve (transport_layer_base *const conn, process_cache *) { assert (conn); @@ -283,9 +279,9 @@ client_request_attach_tty::serve (transport_layer_base * const conn, msglen (0); // Until we fill in some fields. - // verbose: debug_printf ("pid %ld:(%p,%p) -> pid %ld", req.master_pid, - // from_master, to_master, - // req.pid); + // verbose: debug_printf ("pid %ld:(%p,%p) -> pid %ld", + // req.master_pid, req.from_master, req.to_master, + // req.pid); // verbose: debug_printf ("opening process %ld", req.master_pid); @@ -401,66 +397,68 @@ client_request_get_version::serve(transport_layer_base *, process_cache *) class server_request : public queue_request { - public: - server_request (transport_layer_base *newconn, - class process_cache *newcache); - virtual ~server_request(); - virtual void process (); - private: - transport_layer_base *conn; - class process_cache *cache; -}; +public: + server_request (transport_layer_base *const conn, process_cache *const cache) + : _conn (conn), _cache (cache) + {} -class server_process_param : public queue_process_param -{ - public: - transport_layer_base *transport; - server_process_param () : queue_process_param (false) {}; -}; + virtual ~server_request() + { + delete _conn; + } -class server_request_queue : public threaded_queue -{ - public: - class process_cache *cache; - void process_requests (transport_layer_base *transport); - void add_connection (transport_layer_base *conn); -}; + virtual void process () + { + client_request::handle_request (_conn, _cache); + } -class server_request_queue request_queue; +private: + transport_layer_base *const _conn; + process_cache *const _cache; +}; -static DWORD WINAPI -request_loop (LPVOID LpParam) +class server_submission_loop : public queue_submission_loop { - class server_process_param *params = (server_process_param *) LpParam; - class server_request_queue *queue = (server_request_queue *) params->queue; - class transport_layer_base * transport = params->transport; - while (queue->active) +public: + server_submission_loop (threaded_queue *const queue, + transport_layer_base *const transport, + process_cache *const cache) + : queue_submission_loop (queue, false), + _transport (transport), + _cache (cache) { - bool recoverable = false; - transport_layer_base * const new_conn = transport->accept (&recoverable); - if (!new_conn && !recoverable) - { - system_printf ("fatal error on IPC transport: closing down"); - queue->active = false; - } - /* FIXME: this is a little ugly. What we really want is to wait on two objects: - * one for the pipe/socket, and one for being told to shutdown. Otherwise - * this will stay a problem (we won't actually shutdown until the request - * _AFTER_ the shutdown request. And sending ourselves a request is ugly - */ - if (new_conn && queue->active) - queue->add_connection (new_conn); + assert (_transport); + assert (_cache); } - return 0; -} -/* TODO: check we are not being asked to service a already serviced transport */ +private: + transport_layer_base *const _transport; + process_cache *const _cache; + + virtual void request_loop (); +}; + +/* FIXME: this is a little ugly. What we really want is to wait on + * two objects: one for the pipe/socket, and one for being told to + * shutdown. Otherwise this will stay a problem (we won't actually + * shutdown until the request _AFTER_ the shutdown request. And + * sending ourselves a request is ugly + */ void -server_request_queue::process_requests (transport_layer_base *transport) +server_submission_loop::request_loop () { - class server_process_param *params = new server_process_param; - params->transport = transport; - threaded_queue::process_requests (params, request_loop); + while (_running) + { + bool recoverable = false; + transport_layer_base *const conn = _transport->accept (&recoverable); + if (!conn && !recoverable) + { + system_printf ("fatal error on IPC transport: closing down"); + return; + } + if (conn) + _queue->add (new server_request (conn, _cache)); + } } client_request_shutdown::client_request_shutdown () @@ -469,6 +467,8 @@ client_request_shutdown::client_request_shutdown () syscall_printf ("created"); } +static volatile sig_atomic_t shutdown_server = false; + void client_request_shutdown::serve (transport_layer_base *, process_cache *) { @@ -480,55 +480,18 @@ client_request_shutdown::serve (transport_layer_base *, process_cache *) /* FIXME: link upwards, and then this becomes a trivial method call to * only shutdown _this queue_ */ - /* tell the main thread to shutdown */ - request_queue.active = false; - - msglen (0); -} - -server_request::server_request (transport_layer_base *newconn, - class process_cache *newcache) - : conn(newconn), cache(newcache) -{} - -server_request::~server_request () -{ - delete conn; -} -void -server_request::process () -{ - client_request::handle_request (conn, cache); -} + shutdown_server = true; -void -server_request_queue::add_connection (transport_layer_base *conn) -{ - /* safe to not "Try" because workers don't hog this, they wait on the event - */ - /* every derived ::add must enter the section! */ - EnterCriticalSection (&queuelock); - if (!running) - { - delete conn; - LeaveCriticalSection (&queuelock); - return; - } - queue_request * listrequest = new server_request (conn, cache); - add (listrequest); - LeaveCriticalSection (&queuelock); + msglen (0); } static void handle_signal (int signal) { /* any signal makes us die :} */ - /* FIXME: link upwards, and then this becomes a trivial method call to - * only shutdown _this queue_ - */ - /* tell the main thread to shutdown */ - request_queue.active=false; + + shutdown_server = true; } /* @@ -669,53 +632,66 @@ main (const int argc, char *argv[]) return 0; } - if (signal (SIGQUIT, handle_signal) == SIG_ERR) + if (signal (SIGINT, handle_signal) == SIG_ERR) { system_printf ("could not install signal handler (%d)- aborting startup", errno); exit (1); } - transport_layer_base * const transport = create_server_transport (); - assert (transport); print_version (pgm); setbuf (stdout, NULL); printf ("daemon starting up"); - transport->listen (); + + threaded_queue request_queue (10); printf ("."); - class process_cache cache (2); - request_queue.initial_workers = 10; - request_queue.cache = &cache; - request_queue.create_workers (); + + transport_layer_base *const transport = create_server_transport (); + assert (transport); printf ("."); - request_queue.process_requests (transport); + + process_cache cache (2); printf ("."); - cache.create_workers (); + + server_submission_loop submission_loop (&request_queue, transport, &cache); + printf ("."); + + request_queue.add_submission_loop (&submission_loop); printf ("."); - cache.process_requests (); - printf (".complete\n"); - /* TODO: wait on multiple objects - the thread handle for each request loop + - * all the process handles. This should be done by querying the request_queue and - * the process cache for all their handles, and then waiting for (say) 30 seconds. - * after that we recreate the list of handles to wait on, and wait again. - * the point of all this abstraction is that we can trivially server both sockets - * and pipes simply by making a new transport, and then calling - * request_queue.process_requests (transport2); + + transport->listen (); + printf ("."); + + cache.start (); + printf ("."); + + request_queue.start (); + printf ("."); + + printf ("complete\n"); + + /* TODO: wait on multiple objects - the thread handle for each + * request loop + all the process handles. This should be done by + * querying the request_queue and the process cache for all their + * handles, and then waiting for (say) 30 seconds. after that we + * recreate the list of handles to wait on, and wait again. the + * point of all this abstraction is that we can trivially server + * both sockets and pipes simply by making a new transport, and then + * calling request_queue.process_requests (transport2); */ /* WaitForMultipleObjects abort && request_queue && process_queue && signal -- if signal event then retrigger it */ - while (1 && request_queue.active) - { - sleep (1); - } + while (!shutdown_server && request_queue.running () && cache.running ()) + sleep (1); + printf ("\nShutdown request received - new requests will be denied\n"); - request_queue.cleanup (); + request_queue.stop (); printf ("All pending requests processed\n"); delete transport; printf ("No longer accepting requests - cygwin will operate in daemonless mode\n"); - cache.cleanup (); + cache.stop (); printf ("All outstanding process-cache activities completed\n"); printf ("daemon shutdown\n"); |