⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cygserver.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 2 页
字号:
  version.major = CYGWIN_SERVER_VERSION_MAJOR;  version.api   = CYGWIN_SERVER_VERSION_API;  version.minor = CYGWIN_SERVER_VERSION_MINOR;  version.patch = CYGWIN_SERVER_VERSION_PATCH;}class server_request : public queue_request{public:  server_request (transport_layer_base *const conn, process_cache *const cache)    : _conn (conn), _cache (cache)  {}  virtual ~server_request ()  {    safe_delete (_conn);  }  virtual void process ()  {    client_request::handle_request (_conn, _cache);  }private:  transport_layer_base *const _conn;  process_cache *const _cache;};class server_submission_loop : public queue_submission_loop{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)  {    assert (_transport);    assert (_cache);  }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 */voidserver_submission_loop::request_loop (){  /* I'd like the accepting thread's priority to be above any "normal"   * thread in the system to avoid overflowing the listen queue (for   * sockets; similar issues exist for named pipes); but, for example,   * a normal priority thread in a foregrounded process is boosted to   * THREAD_PRIORITY_HIGHEST (AFAICT).  Thus try to set the current   * thread's priority to a level one above that.  This fails on   * win9x/ME so assume any failure in that call is due to that and   * simply call again at one priority level lower.   */  if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST + 1))    if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST))      debug_printf ("failed to raise accept thread priority, error = %lu",		    GetLastError ());  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;	}      // EINTR probably implies a shutdown request; so back off for a      // moment to let the main thread take control, otherwise the      // server spins here receiving EINTR repeatedly since the signal      // handler in the main thread doesn't get a chance to be called.      if (!conn && errno == EINTR)	{	  if (!SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_NORMAL))	    debug_printf ("failed to reset thread priority, error = %lu",			  GetLastError ());	  Sleep (0);	  if (!SetThreadPriority (GetCurrentThread (),				  THREAD_PRIORITY_HIGHEST + 1))	    if (!SetThreadPriority (GetCurrentThread (),				    THREAD_PRIORITY_HIGHEST))	      debug_printf ("failed to raise thread priority, error = %lu",			    GetLastError ());	}      if (conn)	_queue->add (safe_new (server_request, conn, _cache));    }}client_request_shutdown::client_request_shutdown ()  : client_request (CYGSERVER_REQUEST_SHUTDOWN){  // verbose: syscall_printf ("created");}voidclient_request_shutdown::serve (transport_layer_base *, process_cache *){  assert (!error_code ());  if (msglen ())    syscall_printf ("unexpected request body ignored: %lu bytes", msglen ());  /* FIXME: link upwards, and then this becomes a trivial method call to   * only shutdown _this queue_   */  kill (getpid (), SIGINT);  msglen (0);}static sig_atomic_t shutdown_server = false;static voidhandle_signal (const int signum){  /* any signal makes us die :} */  shutdown_server = true;}/* * print_usage () */static voidprint_usage (const char *const pgm){  printf ("Usage: %s [OPTIONS]\n", pgm);  printf ("  -c, --cleanup-threads   number of cleanup threads to use\n");  printf ("  -h, --help              output usage information and exit\n");  printf ("  -r, --request-threads   number of request threads to use\n");  printf ("  -s, --shutdown          shutdown the daemon\n");  printf ("  -v, --version           output version information and exit\n");}/* * print_version () */static voidprint_version (const char *const pgm){  char *vn = NULL;  const char *const colon = strchr (version, ':');  if (!colon)    {      vn = strdup ("?");    }  else    {      vn = strdup (colon + 2);	// Skip ": "      char *const spc = strchr (vn, ' ');      if (spc)	*spc = '\0';    }  char buf[200];  snprintf (buf, sizeof (buf), "%d.%d.%d(%d.%d/%d/%d)-(%d.%d.%d.%d) %s",	    cygwin_version.dll_major / 1000,	    cygwin_version.dll_major % 1000,	    cygwin_version.dll_minor,	    cygwin_version.api_major,	    cygwin_version.api_minor,	    cygwin_version.shared_data,	    CYGWIN_SERVER_VERSION_MAJOR,	    CYGWIN_SERVER_VERSION_API,	    CYGWIN_SERVER_VERSION_MINOR,	    CYGWIN_SERVER_VERSION_PATCH,	    cygwin_version.mount_registry,	    cygwin_version.dll_build_date);  printf ("%s (cygwin) %s\n", pgm, vn);  printf ("API version %s\n", buf);  printf ("Copyright 2001, 2002 Red Hat, Inc.\n");  printf ("Compiled on %s\n", __DATE__);  free (vn);}/* * main () */intmain (const int argc, char *argv[]){  const struct option longopts[] = {    {"cleanup-threads", required_argument, NULL, 'c'},    {"help", no_argument, NULL, 'h'},    {"request-threads", required_argument, NULL, 'r'},    {"shutdown", no_argument, NULL, 's'},    {"version", no_argument, NULL, 'v'},    {0, no_argument, NULL, 0}  };  const char opts[] = "c:hr:sv";  int cleanup_threads = 2;  int request_threads = 10;  bool shutdown = false;  const char *pgm = NULL;  if (!(pgm = strrchr (*argv, '\\')) && !(pgm = strrchr (*argv, '/')))    pgm = *argv;  else    pgm++;  wincap.init ();  if (wincap.has_security ())    setup_privileges ();  int opt;  while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)    switch (opt)      {      case 'c':	cleanup_threads = atoi (optarg);	if (cleanup_threads <= 0)	  {	    fprintf (stderr,		     "%s: number of cleanup threads must be positive\n",		     pgm);	    exit (1);	  }	break;      case 'h':	print_usage (pgm);	return 0;      case 'r':	request_threads = atoi (optarg);	if (request_threads <= 0)	  {	    fprintf (stderr,		     "%s: number of request threads must be positive\n",		     pgm);	    exit (1);	  }	break;      case 's':	shutdown = true;	break;      case 'v':	print_version (pgm);	return 0;      case '?':	fprintf (stderr, "Try `%s --help' for more information.\n", pgm);	exit (1);      }  if (optind != argc)    {      fprintf (stderr, "%s: too many arguments\n", pgm);      exit (1);    }  if (shutdown)    {      /* Setting `cygserver_running' stops the request code making a       * version request, which is not much to the point.       */      cygserver_running = CYGSERVER_OK;      client_request_shutdown req;      if (req.make_request () == -1 || req.error_code ())	{	  fprintf (stderr, "%s: shutdown request failed: %s\n",		   pgm, strerror (req.error_code ()));	  exit (1);	}      // FIXME: It would be nice to wait here for the daemon to exit.      return 0;    }#define SIGHANDLE(SIG)							\  do									\    {									\      struct sigaction act;						\									\      act.sa_handler = &handle_signal;					\      act.sa_mask = 0;							\      act.sa_flags = 0;							\									\      if (sigaction (SIG, &act, NULL) == -1)				\	{								\	  system_printf ("failed to install handler for " #SIG ": %s",	\			 strerror (errno));				\	  exit (1);							\	}								\    } while (false)  SIGHANDLE (SIGHUP);  SIGHANDLE (SIGINT);  SIGHANDLE (SIGTERM);  print_version (pgm);  setbuf (stdout, NULL);  printf ("daemon starting up");  threaded_queue request_queue (request_threads);  printf (".");  transport_layer_base *const transport = create_server_transport ();  assert (transport);  printf (".");  process_cache cache (cleanup_threads);  printf (".");  server_submission_loop submission_loop (&request_queue, transport, &cache);  printf (".");  request_queue.add_submission_loop (&submission_loop);  printf (".");  if (transport->listen () == -1)    {      exit (1);    }  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 (!shutdown_server && request_queue.running () && cache.running ())    pause ();  printf ("\nShutdown request received - new requests will be denied\n");  request_queue.stop ();  printf ("All pending requests processed\n");  safe_delete (transport);  printf ("No longer accepting requests - cygwin will operate in daemonless mode\n");  cache.stop ();  printf ("All outstanding process-cache activities completed\n");  printf ("daemon shutdown\n");  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -