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

📄 fork.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 2 页
字号:
    CloseHandle (console_handle);  else    c_flags |= DETACHED_PROCESS;  /* Some file types (currently only sockets) need extra effort in the     parent after CreateProcess and before copying the datastructures     to the child. So we have to start the child in suspend state,     unfortunately, to avoid a race condition. */  if (cygheap->fdtab.need_fixup_before ())    c_flags |= CREATE_SUSPENDED;  /* Create an inheritable handle to pass to the child process.  This will     allow the child to duplicate handles from the parent to itself. */  hParent = NULL;  if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hParent, 0, 1,			DUPLICATE_SAME_ACCESS))    {      system_printf ("couldn't create handle to myself for child, %E");      return -1;    }  /* Remember the address of the first loaded dll and decide     if we need to load dlls.  We do this here so that this     information will be available in the parent and, when     the stack is copied, in the child. */  first_dll = dlls.start.next;  load_dlls = dlls.reload_on_fork && dlls.loaded_dlls;  /* This will help some of the confusion.  */  fflush (stdout);  subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL);  if (subproc_ready == NULL)    {      CloseHandle (hParent);      system_printf ("unable to allocate subproc_ready event, %E");      return -1;    }  forker_finished = CreateEvent (&sec_all, FALSE, FALSE, NULL);  if (forker_finished == NULL)    {      CloseHandle (hParent);      CloseHandle (subproc_ready);      system_printf ("unable to allocate forker_finished event, %E");      return -1;    }  ProtectHandleINH (subproc_ready);  ProtectHandleINH (forker_finished);  init_child_info (PROC_FORK, &ch, 1, subproc_ready);  ch.forker_finished = forker_finished;  stack_base (ch);  si.cb = sizeof (STARTUPINFO);  si.lpReserved2 = (LPBYTE)&ch;  si.cbReserved2 = sizeof (ch);  /* Remove impersonation */  if (cygheap->user.issetuid ())    RevertToSelf ();  ch.parent = hParent;#ifdef DEBUGGING  if (npid_max)    {      for (int pass = 0; pass < 2; pass++)	{	  pid_t pid;	  while ((pid = fork_pids[npid++]))	    if (!pinfo (pid))	      {		ch.cygpid = pid;		goto out;	      }	  npid = 0;	}    } out:#endif  char sa_buf[1024];  PSECURITY_ATTRIBUTES sec_attribs = sec_user_nih (sa_buf);  syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %x, 0, 0, %p, %p)",		  myself->progname, myself->progname, c_flags, &si, &pi);  __malloc_lock ();  void *newheap;  newheap = cygheap_setup_for_child (&ch, cygheap->fdtab.need_fixup_before ());  rc = CreateProcess (myself->progname, /* image to run */		      myself->progname, /* what we send in arg0 */		      sec_attribs,		      sec_attribs,		      TRUE,	  /* inherit handles from parent */		      c_flags,		      NULL,	  /* environment filled in later */		      0,	  /* use current drive/directory */		      &si,		      &pi);  CloseHandle (hParent);  if (!rc)    {      __seterrno ();      syscall_printf ("CreateProcessA failed, %E");      ForceCloseHandle (subproc_ready);      ForceCloseHandle (forker_finished);      /* Restore impersonation */      if (cygheap->user.issetuid ())	ImpersonateLoggedOnUser (cygheap->user.token);      cygheap_setup_for_child_cleanup (newheap, &ch, 0);      return -1;    }  /* Fixup the parent datastructure if needed and resume the child's     main thread. */  if (!cygheap->fdtab.need_fixup_before ())    cygheap_setup_for_child_cleanup (newheap, &ch, 0);  else    {      cygheap->fdtab.fixup_before_fork (pi.dwProcessId);      cygheap_setup_for_child_cleanup (newheap, &ch, 1);      ResumeThread (pi.hThread);    }#ifdef DEBUGGING  pinfo forked ((ch.cygpid != 1 ? ch.cygpid : cygwin_pid (pi.dwProcessId)), 1);#else  pinfo forked (cygwin_pid (pi.dwProcessId), 1);#endif  /* Initialize things that are done later in dll_crt0_1 that aren't done     for the forkee.  */  strcpy (forked->progname, myself->progname);  /* Restore impersonation */  if (cygheap->user.issetuid ())    ImpersonateLoggedOnUser (cygheap->user.token);  ProtectHandle (pi.hThread);  /* Protect the handle but name it similarly to the way it will     be called in subproc handling. */  ProtectHandle1 (pi.hProcess, childhProc);  /* Fill in fields in the child's process table entry.  */  forked->hProcess = pi.hProcess;  forked->dwProcessId = pi.dwProcessId;  forked->copysigs (myself);  /* Hopefully, this will succeed.  The alternative to doing things this     way is to reserve space prior to calling CreateProcess and then fill     it in afterwards.  This requires more bookkeeping than I like, though,     so we'll just do it the easy way.  So, terminate any child process if     we can't actually record the pid in the internal table. */  if (!forked.remember ())    {      TerminateProcess (pi.hProcess, 1);      set_errno (EAGAIN);      goto cleanup;    }  slow_pid_reuse (pi.hProcess);  /* Wait for subproc to initialize itself. */  if (!sync_with_child (pi, subproc_ready, TRUE, "waiting for longjmp"))    goto cleanup;  /* CHILD IS STOPPED */  debug_printf ("child is alive (but stopped)");  /* Initialize, in order: data, bss, heap, stack, dll data, dll bss     Note: variables marked as NO_COPY will not be copied     since they are placed in a protected segment. */  MALLOC_CHECK;  rc = fork_copy (pi, "user/cygwin data",		  user_data->data_start, user_data->data_end,		  user_data->bss_start, user_data->bss_end,		  cygheap->user_heap.base, cygheap->user_heap.ptr,		  stack_here, ch.stackbottom,		  dll_data_start, dll_data_end,		  dll_bss_start, dll_bss_end, NULL);  __malloc_unlock ();  MALLOC_CHECK;  if (!rc)    goto cleanup;  /* Now fill data/bss of any DLLs that were linked into the program. */  for (dll *d = dlls.istart (DLL_LINK); d; d = dlls.inext ())    {      debug_printf ("copying data/bss of a linked dll");      if (!fork_copy (pi, "linked dll data/bss", d->p.data_start, d->p.data_end,						 d->p.bss_start, d->p.bss_end,						 NULL))	goto cleanup;    }  /* Start thread, and wait for it to reload dlls.  */  if (!resume_child (pi, forker_finished) ||      !sync_with_child (pi, subproc_ready, load_dlls, "child loading dlls"))    goto cleanup;  /* If DLLs were loaded in the parent, then the child has reloaded all     of them and is now waiting to have all of the individual data and     bss sections filled in. */  if (load_dlls)    {      /* CHILD IS STOPPED */      /* write memory of reloaded dlls */      for (dll *d = dlls.istart (DLL_LOAD); d; d = dlls.inext ())	{	  debug_printf ("copying data/bss for a loaded dll");	  if (!fork_copy (pi, "loaded dll data/bss", d->p.data_start, d->p.data_end,						     d->p.bss_start, d->p.bss_end,						     NULL))	    goto cleanup;	}      /* Start the child up again. */      (void) resume_child (pi, forker_finished);    }  ForceCloseHandle (subproc_ready);  ForceCloseHandle (pi.hThread);  ForceCloseHandle (forker_finished);  forker_finished = NULL;  pi.hThread = NULL;  pthread::atforkparent ();  return forked->pid;/* Common cleanup code for failure cases */ cleanup:  /* Remember to de-allocate the fd table. */  if (pi.hProcess)    ForceCloseHandle1 (pi.hProcess, childhProc);  if (pi.hThread)    ForceCloseHandle (pi.hThread);  if (subproc_ready)    ForceCloseHandle (subproc_ready);  if (forker_finished)    ForceCloseHandle (forker_finished);  return -1;}extern "C" intfork (){  struct  {    HANDLE hParent;    dll *first_dll;    bool load_dlls;  } grouped;  MALLOC_CHECK;  sigframe thisframe (mainthread);  debug_printf ("entering");  grouped.hParent = grouped.first_dll = NULL;  grouped.load_dlls = 0;  if (ISSTATE(myself, PID_SPLIT_HEAP))    {      system_printf ("The heap has been split, CYGWIN can't fork this process.");      system_printf ("Increase the heap_chunk_size in the registry and try again.");      set_errno (ENOMEM);      syscall_printf ("-1 = fork (), split heap");      return -1;    }  void *esp;  __asm__ volatile ("movl %%esp,%0": "=r" (esp));  myself->set_has_pgid_children ();  child_info_fork ch;  int res = setjmp (ch.jmp);  if (res)    res = fork_child (grouped.hParent, grouped.first_dll, grouped.load_dlls);  else    res = fork_parent (grouped.hParent, grouped.first_dll, grouped.load_dlls, esp, ch);  MALLOC_CHECK;  syscall_printf ("%d = fork()", res);  return res;}#ifdef DEBUGGINGvoidfork_init (){  char buf[1024];  if (!GetEnvironmentVariable ("CYGWIN_FORK_PIDS", buf, 1024))    return;  pid_t pid;  char *p, *pe;  for (p = buf; (pid = strtol (p, &pe, 10)); p = pe)    fork_pids[npid_max++] = pid;}#endif /*DEBUGGING*/#ifdef NEWVFORK/* Dummy function to force second assignment below to actually be   carried out */static vfork_save *get_vfork_val (){  return vfork_storage.val ();}#endifextern "C" intvfork (){#ifndef NEWVFORK  return fork ();#else  sigframe thisframe;  vfork_save *vf = get_vfork_val ();  char **esp, **pp;  if (vf == NULL)    vf = vfork_storage.create ();  else if (vf->pid)    return fork ();  if (!setjmp (vf->j))    {      vf->pid = -1;      __asm__ volatile ("movl %%esp,%0": "=r" (vf->vfork_esp):);      __asm__ volatile ("movl %%ebp,%0": "=r" (vf->vfork_ebp):);      for (pp = (char **)vf->frame, esp = vf->vfork_esp;	   esp <= vf->vfork_ebp + 2; pp++, esp++)	*pp = *esp;      vf->ctty = myself->ctty;      vf->sid = myself->sid;      vf->pgid = myself->pgid;      int res = cygheap->fdtab.vfork_child_dup () ? 0 : -1;      debug_printf ("%d = vfork()", res);      return res;    }  vf = get_vfork_val ();  for (pp = (char **)vf->frame, esp = vf->vfork_esp;       esp <= vf->vfork_ebp + 2; pp++, esp++)    *esp = *pp;  thisframe.init (mainthread);  cygheap->fdtab.vfork_parent_restore ();  myself->ctty = vf->ctty;  myself->sid = vf->sid;  myself->pgid = vf->pgid;  if (vf->pid < 0)    {      int exitval = vf->exitval;      vf->pid = 0;      if ((vf->pid = fork ()) == 0)	exit (exitval);    }  int pid = vf->pid;  vf->pid = 0;  debug_printf ("exiting vfork, pid %d", pid);  sig_dispatch_pending ();  return pid;#endif}

⌨️ 快捷键说明

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