dcrt0.cc

来自「cygwin, 著名的在win32下模拟unix操作系统的东东」· CC 代码 · 共 1,134 行 · 第 1/2 页

CC
1,134
字号
  mainthread.init ("mainthread"); // For use in determining if signals				  //  should be blocked.  int envc = 0;  char **envp = NULL;  if (!child_proc_info)    memory_init ();  else    {      bool close_ppid_handle = false;      bool close_hexec_proc = false;      switch (child_proc_info->type)	{	  case _PROC_FORK:	    alloc_stack (fork_info);	    cygheap_fixup_in_child (0);	    memory_init ();	    set_myself (mypid);	    close_ppid_handle = !!child_proc_info->pppid_handle;	    break;	  case _PROC_SPAWN:	    /* Have to delay closes until after cygheap is setup */	    close_hexec_proc = !!spawn_info->hexec_proc;	    close_ppid_handle = !!child_proc_info->pppid_handle;	    goto around;	  case _PROC_EXEC:	    hexec_proc = spawn_info->hexec_proc;	  around:	    HANDLE h;	    cygheap_fixup_in_child (1);	    memory_init ();	    if (!spawn_info->moreinfo->myself_pinfo ||		!DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,				  hMainProc, &h, 0, 0,				  DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))	      h = NULL;	    set_myself (mypid, h);	    __argc = spawn_info->moreinfo->argc;	    __argv = spawn_info->moreinfo->argv;	    envp = spawn_info->moreinfo->envp;	    envc = spawn_info->moreinfo->envc;	    cygheap->fdtab.fixup_after_exec (spawn_info->parent);	    signal_fixup_after_exec (child_proc_info->type == PROC_SPAWN);	    CloseHandle (spawn_info->parent);	    if (spawn_info->moreinfo->old_title)	      {		old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);		cfree (spawn_info->moreinfo->old_title);	      }	    break;	}      if (close_hexec_proc)	CloseHandle (spawn_info->hexec_proc);      if (close_ppid_handle)	CloseHandle (child_proc_info->pppid_handle);    }  ProtectHandle (hMainProc);  ProtectHandle (hMainThread);  cygthread::init ();  pthread::initMainThread (!user_data->forkee);  /* Initialize debug muto, if DLL is built with --enable-debugging.     Need to do this before any helper threads start. */  debug_init ();  cygheap->fdtab.vfork_child_fixup ();  (void) SetErrorMode (SEM_FAILCRITICALERRORS);  /* Initialize events. */  events_init ();  cygheap->cwd.init ();  main_vfork = vfork_storage.create ();  cygbench ("pre-forkee");  if (user_data->forkee)    {      /* If we've played with the stack, stacksize != 0.  That means that	 fork() was invoked from other than the main thread.  Make sure that	 frame pointer is referencing the new stack so that the OS knows what	 to do when it needs to increase the size of the stack.	 NOTE: Don't do anything that involves the stack until you've completed	 this step. */      if (fork_info->stacksize)	{	  asm ("movl %0,%%fs:4" : : "r" (fork_info->stackbottom));	  asm ("movl %0,%%fs:8" : : "r" (fork_info->stacktop));	}      longjmp (fork_info->jmp, fork_info->cygpid);    }#ifdef DEBUGGING  {  extern void fork_init ();  fork_init ();  }#endif  /* Initialize our process table entry. */  pinfo_init (envp, envc);  if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))      old_title = title_buf;  /* Allocate cygheap->fdtab */  dtable_init ();  /* Initialize uid, gid if necessary. */  if (child_proc_info == NULL || spawn_info->moreinfo->uid == ILLEGAL_UID)    uinfo_init ();  /* Initialize signal/subprocess handling. */  sigproc_init ();  /* Connect to tty. */  tty_init ();  if (!__argc)    {      char *line = GetCommandLineA ();      line = strcpy ((char *) alloca (strlen (line) + 1), line);      if (current_codepage == oem_cp)	CharToOemA (line, line);      /* Scan the command line and build argv.  Expand wildcards if not	 called from another cygwin process. */      build_argv (line, __argv, __argc,		  NOTSTATE (myself, PID_CYGPARENT) && allow_glob);      /* Convert argv[0] to posix rules if it's currently blatantly	 win32 style. */      if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))	{	  char *new_argv0 = (char *) alloca (MAX_PATH);	  cygwin_conv_to_posix_path (__argv[0], new_argv0);	  __argv[0] = new_argv0;	}    }  if (user_data->premain[0])    for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)      user_data->premain[i] (__argc, __argv, user_data);  /* Set up standard fds in file descriptor table. */  cygheap->fdtab.stdio_init ();  /* Set up __progname for getopt error call. */  if (__argv[0] && (__progname = strrchr (__argv[0], '/')))    ++__progname;  else    __progname = __argv[0];  if (__progname)    {      char *cp = strchr (__progname, '\0') - 4;      if (cp > __progname && strcasematch (cp, ".exe"))	*cp = '\0';    }  /* Set new console title if appropriate. */  if (display_title && !dynamically_loaded)    {      char *cp = __progname;      if (strip_title_path)	for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)	  if (isdirsep (*ptr))	    cp = ptr + 1;      set_console_title (cp);    }  cygwin_finished_initializing = 1;  /* Call init of loaded dlls. */  dlls.init ();  /* Execute any specified "premain" functions */  if (user_data->premain[PREMAIN_LEN / 2])    for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)      user_data->premain[i] (__argc, __argv, user_data);  debug_printf ("user_data->main %p", user_data->main);  if (dynamically_loaded)    {      set_errno (0);      return;    }  /* Disable case-insensitive globbing */  ignore_case_with_glob = FALSE;  /* Flush signals and ensure that signal thread is up and running. Can't     do this for noncygwin case since the signal thread is blocked due to     LoadLibrary serialization. */  wait_for_sigthread ();  set_errno (0);  MALLOC_CHECK;  cygbench (__progname);  if (user_data->main)    exit (user_data->main (__argc, __argv, *user_data->envptr));}#ifdef DEBUGGINGvoidbreak_here (){  debug_printf ("break here");}#endifvoidinitial_env (){  DWORD len;  char buf[MAX_PATH + 1];#ifdef DEBUGGING  if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))    {      DWORD ms = atoi (buf);      buf[0] = '\0';      len = GetModuleFileName (NULL, buf, MAX_PATH);      console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);      Sleep (ms);    }  if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))    {      char buf1[MAX_PATH + 1];      len = GetModuleFileName (NULL, buf1, MAX_PATH);      strlwr (buf1);      strlwr (buf);      char *p = strchr (buf, '=');      if (!p)	p = (char *) "gdb.exe -nw";      else	*p++ = '\0';      if (strstr (buf1, buf))	{	  error_start_init (p);	  try_to_debug ();	  break_here ();	}    }#endif  if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1))    {      _cygwin_testing = 1;      if ((len = GetModuleFileName (cygwin_hmodule, buf, MAX_PATH))	  && len > sizeof ("new-cygwin1.dll")	  && strcasematch (buf + len - sizeof ("new-cygwin1.dll"),			   "\\new-cygwin1.dll"))	_cygwin_testing_magic = 0x10;    }}/* Wrap the real one, otherwise gdb gets confused about   two symbols with the same name, but different addresses.   UPTR is a pointer to global data that lives on the libc side of the   line [if one distinguishes the application from the dll].  */extern "C" void __stdcall_dll_crt0 (){  DECLARE_TLS_STORAGE;  initial_env ();  char zeros[sizeof (fork_info->zero)] = {0};  static NO_COPY STARTUPINFO si;#ifdef DEBUGGING  strace.microseconds ();#endif  main_environ = user_data->envptr;  *main_environ = NULL;  early_stuff_init ();  if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),		       GetCurrentProcess (), &hMainProc, 0, FALSE,			DUPLICATE_SAME_ACCESS))    hMainProc = GetCurrentProcess ();  DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,		   &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);  GetStartupInfo (&si);  child_proc_info = (child_info *) si.lpReserved2;  if (si.cbReserved2 < EXEC_MAGIC_SIZE || !child_proc_info      || memcmp (child_proc_info->zero, zeros, sizeof (zeros)) != 0)    child_proc_info = NULL;  else    {      if ((child_proc_info->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)	multiple_cygwin_problem ("proc", child_proc_info->intro, 0);      else if (child_proc_info->intro == PROC_MAGIC_GENERIC	       && child_proc_info->magic != CHILD_INFO_MAGIC)	multiple_cygwin_problem ("proc", child_proc_info->magic,				 CHILD_INFO_MAGIC);      else if (child_proc_info->cygheap != (void *) &_cygheap_start)	multiple_cygwin_problem ("cygheap", (DWORD) child_proc_info->cygheap,				 (DWORD) &_cygheap_start);      unsigned should_be_cb = 0;      switch (child_proc_info->type)	{	  case _PROC_FORK:	    user_data->forkee = child_proc_info->cygpid;	    should_be_cb = sizeof (child_info_fork);	    /* fall through */;	  case _PROC_SPAWN:	  case _PROC_EXEC:	    if (!should_be_cb)	      should_be_cb = sizeof (child_info);	    if (should_be_cb != child_proc_info->cb)	      multiple_cygwin_problem ("proc size", child_proc_info->cb, should_be_cb);	    else if (sizeof (fhandler_union) != child_proc_info->fhandler_union_cb)	      multiple_cygwin_problem ("fhandler size", child_proc_info->fhandler_union_cb, sizeof (fhandler_union));	    else	      {		cygwin_mount_h = child_proc_info->mount_h;		mypid = child_proc_info->cygpid;		break;	      }	  default:	    system_printf ("unknown exec type %d", child_proc_info->type);	    /* intentionally fall through */	  case _PROC_WHOOPS:	    child_proc_info = NULL;	    break;	}    }  dll_crt0_1 ();}voiddll_crt0 (per_process *uptr){  DECLARE_TLS_STORAGE;  /* Set the local copy of the pointer into the user space. */  if (uptr && uptr != user_data)    {      memcpy (user_data, uptr, per_process_overwrite);      *(user_data->impure_ptr_ptr) = &reent_data;    }  _dll_crt0 ();}/* This must be called by anyone who uses LoadLibrary to load cygwin1.dll */extern "C" voidcygwin_dll_init (){  static char **envp;  static int _fmode;  if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),		       GetCurrentProcess (), &hMainProc, 0, FALSE,			DUPLICATE_SAME_ACCESS))    hMainProc = GetCurrentProcess ();  DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,		   &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS);  user_data->magic_biscuit = sizeof (per_process);  user_data->envptr = &envp;  user_data->fmode_ptr = &_fmode;  dll_crt0_1 ();}extern "C" void__main (void){  do_global_ctors (user_data->ctors, FALSE);}enum exit_states  {    ES_NOT_EXITING = 0,    ES_THREADTERM,    ES_SIGNAL,    ES_CLOSEALL,    ES_SIGPROCTERMINATE,    ES_TITLE,    ES_HUP_PGRP,    ES_HUP_SID,    ES_TTY_TERMINATE,    ES_EVENTS_TERMINATE  };exit_states NO_COPY exit_state;extern "C" void __stdcalldo_exit (int status){  UINT n = (UINT) status;  syscall_printf ("do_exit (%d)", n);  vfork_save *vf = vfork_storage.val ();  if (vf != NULL && vf->pid < 0)    vf->restore_exit (status);  if (exit_state < ES_THREADTERM)    {      exit_state = ES_THREADTERM;      cygthread::terminate ();    }  if (exit_state < ES_SIGNAL)    {      exit_state = ES_SIGNAL;      if (!(n & EXIT_REPARENTING))	{	  signal (SIGCHLD, SIG_IGN);	  signal (SIGHUP, SIG_IGN);	  signal (SIGINT, SIG_IGN);	  signal (SIGQUIT, SIG_IGN);	}    }  if (exit_state < ES_CLOSEALL)    {      exit_state = ES_CLOSEALL;      close_all_files ();    }  if (exit_state < ES_SIGPROCTERMINATE)    {      exit_state = ES_SIGPROCTERMINATE;      sigproc_terminate ();    }  myself->stopsig = 0;  if (exit_state < ES_TITLE)    {      exit_state = ES_TITLE;      /* restore console title */      if (old_title && display_title)	set_console_title (old_title);    }  if (exit_state < ES_HUP_PGRP)    {      exit_state = ES_HUP_PGRP;      /* Kill orphaned children on group leader exit */      if (myself->has_pgid_children && myself->pid == myself->pgid)	{	  sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",			  myself->pid, myself->pgid);	  kill_pgrp (myself->pgid, -SIGHUP);	}    }  if (exit_state < ES_HUP_SID)    {      exit_state = ES_HUP_SID;      /* Kill the foreground process group on session leader exit */      if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))	{	  tty *tp = cygwin_shared->tty[myself->ctty];	  sigproc_printf ("%d == sid %d, send SIGHUP to children",			  myself->pid, myself->sid);	/* CGF FIXME: This can't be right. */	  if (tp->getsid () == myself->sid)	    tp->kill_pgrp (SIGHUP);	}    }  if (exit_state < ES_TTY_TERMINATE)    {      exit_state = ES_TTY_TERMINATE;      tty_terminate ();    }  if (exit_state < ES_EVENTS_TERMINATE)    {      exit_state = ES_EVENTS_TERMINATE;      events_terminate ();    }  minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);  myself->exit (n);}extern "C" void_exit (int n){  do_exit ((DWORD) n & 0xffff);}extern "C" void__api_fatal (const char *fmt, ...){  char buf[4096];  va_list ap;  va_start (ap, fmt);  __small_vsprintf (buf, fmt, ap);  va_end (ap);  strcat (buf, "\n");  int len = strlen (buf);  DWORD done;  (void) WriteFile (GetStdHandle (STD_ERROR_HANDLE), buf, len, &done, 0);  /* Make sure that the message shows up on the screen, too, since this is     a serious error. */  if (GetFileType (GetStdHandle (STD_ERROR_HANDLE)) != FILE_TYPE_CHAR)    {      HANDLE h = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE,			     FILE_SHARE_WRITE | FILE_SHARE_WRITE,			     &sec_none, OPEN_EXISTING, 0, 0);      if (h != INVALID_HANDLE_VALUE)	(void) WriteFile (h, buf, len, &done, 0);    }  /* We are going down without mercy.  Make sure we reset     our process_state. */  sigproc_terminate ();#ifdef DEBUGGING  (void) try_to_debug ();#endif  myself->exit (1);}voidmultiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version){  if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))    {      child_proc_info->type = _PROC_WHOOPS;      return;    }  char buf[1024];  if (GetEnvironmentVariable ("CYGWIN_MISMATCH_OK", buf, sizeof (buf)))    return;  if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)    system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);  else    api_fatal ("%s version mismatch detected - %p/%p.\n\You have multiple copies of cygwin1.dll on your system.\n\Search for cygwin1.dll using the Windows Start->Find/Search facility\n\and delete all but the most recent version.  The most recent version *should*\n\reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\installed the cygwin distribution.", what, magic_version, version);}#ifdef DEBUGGINGvoid __stdcallcygbench (const char *s){  char buf[1024];  if (GetEnvironmentVariable ("CYGWIN_BENCH", buf, sizeof (buf)))    small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());}#endif

⌨️ 快捷键说明

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