diff --git a/Process.h.in b/Process.h.in
index e35939f399a203921244c5a8ca29ec5cd52e379d..c5ebc97f4f53790077b6197d3706ff9a4f3cffed 100644
--- a/Process.h.in
+++ b/Process.h.in
@@ -23,58 +23,60 @@
 # define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
 #endif
 #if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
-# define kwsysProcess                     kwsys_ns(Process)
-# define kwsysProcess_s                   kwsys_ns(Process_s)
-# define kwsysProcess_New                 kwsys_ns(Process_New)
-# define kwsysProcess_Delete              kwsys_ns(Process_Delete)
-# define kwsysProcess_SetCommand          kwsys_ns(Process_SetCommand)
-# define kwsysProcess_AddCommand          kwsys_ns(Process_AddCommand)
-# define kwsysProcess_SetTimeout          kwsys_ns(Process_SetTimeout)
-# define kwsysProcess_SetWorkingDirectory kwsys_ns(Process_SetWorkingDirectory)
-# define kwsysProcess_SetPipeFile         kwsys_ns(Process_SetPipeFile)
-# define kwsysProcess_SetPipeNative       kwsys_ns(Process_SetPipeNative)
-# define kwsysProcess_SetPipeShared       kwsys_ns(Process_SetPipeShared)
-# define kwsysProcess_Option_Detach       kwsys_ns(Process_Option_Detach)
-# define kwsysProcess_Option_HideWindow   kwsys_ns(Process_Option_HideWindow)
-# define kwsysProcess_Option_MergeOutput  kwsys_ns(Process_Option_MergeOutput)
-# define kwsysProcess_Option_Verbatim     kwsys_ns(Process_Option_Verbatim)
-# define kwsysProcess_GetOption           kwsys_ns(Process_GetOption)
-# define kwsysProcess_SetOption           kwsys_ns(Process_SetOption)
-# define kwsysProcess_Option_e            kwsys_ns(Process_Option_e)
-# define kwsysProcess_State_Starting      kwsys_ns(Process_State_Starting)
-# define kwsysProcess_State_Error         kwsys_ns(Process_State_Error)
-# define kwsysProcess_State_Exception     kwsys_ns(Process_State_Exception)
-# define kwsysProcess_State_Executing     kwsys_ns(Process_State_Executing)
-# define kwsysProcess_State_Exited        kwsys_ns(Process_State_Exited)
-# define kwsysProcess_State_Expired       kwsys_ns(Process_State_Expired)
-# define kwsysProcess_State_Killed        kwsys_ns(Process_State_Killed)
-# define kwsysProcess_State_Disowned      kwsys_ns(Process_State_Disowned)
-# define kwsysProcess_GetState            kwsys_ns(Process_GetState)
-# define kwsysProcess_State_e             kwsys_ns(Process_State_e)
-# define kwsysProcess_Exception_None      kwsys_ns(Process_Exception_None)
-# define kwsysProcess_Exception_Fault     kwsys_ns(Process_Exception_Fault)
-# define kwsysProcess_Exception_Illegal   kwsys_ns(Process_Exception_Illegal)
-# define kwsysProcess_Exception_Interrupt kwsys_ns(Process_Exception_Interrupt)
-# define kwsysProcess_Exception_Numerical kwsys_ns(Process_Exception_Numerical)
-# define kwsysProcess_Exception_Other     kwsys_ns(Process_Exception_Other)
-# define kwsysProcess_GetExitException    kwsys_ns(Process_GetExitException)
-# define kwsysProcess_Exception_e         kwsys_ns(Process_Exception_e)
-# define kwsysProcess_GetExitCode         kwsys_ns(Process_GetExitCode)
-# define kwsysProcess_GetExitValue        kwsys_ns(Process_GetExitValue)
-# define kwsysProcess_GetErrorString      kwsys_ns(Process_GetErrorString)
-# define kwsysProcess_GetExceptionString  kwsys_ns(Process_GetExceptionString)
-# define kwsysProcess_Execute             kwsys_ns(Process_Execute)
-# define kwsysProcess_Disown              kwsys_ns(Process_Disown)
-# define kwsysProcess_WaitForData         kwsys_ns(Process_WaitForData)
-# define kwsysProcess_Pipes_e             kwsys_ns(Process_Pipes_e)
-# define kwsysProcess_Pipe_None           kwsys_ns(Process_Pipe_None)
-# define kwsysProcess_Pipe_STDIN          kwsys_ns(Process_Pipe_STDIN)
-# define kwsysProcess_Pipe_STDOUT         kwsys_ns(Process_Pipe_STDOUT)
-# define kwsysProcess_Pipe_STDERR         kwsys_ns(Process_Pipe_STDERR)
-# define kwsysProcess_Pipe_Timeout        kwsys_ns(Process_Pipe_Timeout)
-# define kwsysProcess_Pipe_Handle         kwsys_ns(Process_Pipe_Handle)
-# define kwsysProcess_WaitForExit         kwsys_ns(Process_WaitForExit)
-# define kwsysProcess_Kill                kwsys_ns(Process_Kill)
+# define kwsysProcess                           kwsys_ns(Process)
+# define kwsysProcess_s                         kwsys_ns(Process_s)
+# define kwsysProcess_New                       kwsys_ns(Process_New)
+# define kwsysProcess_Delete                    kwsys_ns(Process_Delete)
+# define kwsysProcess_SetCommand                kwsys_ns(Process_SetCommand)
+# define kwsysProcess_AddCommand                kwsys_ns(Process_AddCommand)
+# define kwsysProcess_SetTimeout                kwsys_ns(Process_SetTimeout)
+# define kwsysProcess_SetWorkingDirectory       kwsys_ns(Process_SetWorkingDirectory)
+# define kwsysProcess_SetPipeFile               kwsys_ns(Process_SetPipeFile)
+# define kwsysProcess_SetPipeNative             kwsys_ns(Process_SetPipeNative)
+# define kwsysProcess_SetPipeShared             kwsys_ns(Process_SetPipeShared)
+# define kwsysProcess_Option_Detach             kwsys_ns(Process_Option_Detach)
+# define kwsysProcess_Option_HideWindow         kwsys_ns(Process_Option_HideWindow)
+# define kwsysProcess_Option_MergeOutput        kwsys_ns(Process_Option_MergeOutput)
+# define kwsysProcess_Option_Verbatim           kwsys_ns(Process_Option_Verbatim)
+# define kwsysProcess_Option_CreateProcessGroup kwsys_ns(Process_Option_CreateProcessGroup)
+# define kwsysProcess_GetOption                 kwsys_ns(Process_GetOption)
+# define kwsysProcess_SetOption                 kwsys_ns(Process_SetOption)
+# define kwsysProcess_Option_e                  kwsys_ns(Process_Option_e)
+# define kwsysProcess_State_Starting            kwsys_ns(Process_State_Starting)
+# define kwsysProcess_State_Error               kwsys_ns(Process_State_Error)
+# define kwsysProcess_State_Exception           kwsys_ns(Process_State_Exception)
+# define kwsysProcess_State_Executing           kwsys_ns(Process_State_Executing)
+# define kwsysProcess_State_Exited              kwsys_ns(Process_State_Exited)
+# define kwsysProcess_State_Expired             kwsys_ns(Process_State_Expired)
+# define kwsysProcess_State_Killed              kwsys_ns(Process_State_Killed)
+# define kwsysProcess_State_Disowned            kwsys_ns(Process_State_Disowned)
+# define kwsysProcess_GetState                  kwsys_ns(Process_GetState)
+# define kwsysProcess_State_e                   kwsys_ns(Process_State_e)
+# define kwsysProcess_Exception_None            kwsys_ns(Process_Exception_None)
+# define kwsysProcess_Exception_Fault           kwsys_ns(Process_Exception_Fault)
+# define kwsysProcess_Exception_Illegal         kwsys_ns(Process_Exception_Illegal)
+# define kwsysProcess_Exception_Interrupt       kwsys_ns(Process_Exception_Interrupt)
+# define kwsysProcess_Exception_Numerical       kwsys_ns(Process_Exception_Numerical)
+# define kwsysProcess_Exception_Other           kwsys_ns(Process_Exception_Other)
+# define kwsysProcess_GetExitException          kwsys_ns(Process_GetExitException)
+# define kwsysProcess_Exception_e               kwsys_ns(Process_Exception_e)
+# define kwsysProcess_GetExitCode               kwsys_ns(Process_GetExitCode)
+# define kwsysProcess_GetExitValue              kwsys_ns(Process_GetExitValue)
+# define kwsysProcess_GetErrorString            kwsys_ns(Process_GetErrorString)
+# define kwsysProcess_GetExceptionString        kwsys_ns(Process_GetExceptionString)
+# define kwsysProcess_Execute                   kwsys_ns(Process_Execute)
+# define kwsysProcess_Disown                    kwsys_ns(Process_Disown)
+# define kwsysProcess_WaitForData               kwsys_ns(Process_WaitForData)
+# define kwsysProcess_Pipes_e                   kwsys_ns(Process_Pipes_e)
+# define kwsysProcess_Pipe_None                 kwsys_ns(Process_Pipe_None)
+# define kwsysProcess_Pipe_STDIN                kwsys_ns(Process_Pipe_STDIN)
+# define kwsysProcess_Pipe_STDOUT               kwsys_ns(Process_Pipe_STDOUT)
+# define kwsysProcess_Pipe_STDERR               kwsys_ns(Process_Pipe_STDERR)
+# define kwsysProcess_Pipe_Timeout              kwsys_ns(Process_Pipe_Timeout)
+# define kwsysProcess_Pipe_Handle               kwsys_ns(Process_Pipe_Handle)
+# define kwsysProcess_WaitForExit               kwsys_ns(Process_WaitForExit)
+# define kwsysProcess_Interrupt                 kwsys_ns(Process_Interrupt)
+# define kwsysProcess_Kill                      kwsys_ns(Process_Kill)
 #endif
 
 #if defined(__cplusplus)
@@ -199,6 +201,15 @@ kwsysEXPORT void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe,
  *                                 and ignore the rest of the arguments.
  *         0 = No (default)
  *         1 = Yes
+ *
+ *  kwsysProcess_Option_CreateProcessGroup = Whether to place the process in a
+ *                                           new process group.  This is
+ *                                           useful if you want to send Ctrl+C
+ *                                           to the process.  On UNIX, also
+ *                                           places the process in a new
+ *                                           session.
+ *         0 = No (default)
+ *         1 = Yes
  */
 kwsysEXPORT int kwsysProcess_GetOption(kwsysProcess* cp, int optionId);
 kwsysEXPORT void kwsysProcess_SetOption(kwsysProcess* cp, int optionId,
@@ -208,7 +219,8 @@ enum kwsysProcess_Option_e
   kwsysProcess_Option_HideWindow,
   kwsysProcess_Option_Detach,
   kwsysProcess_Option_MergeOutput,
-  kwsysProcess_Option_Verbatim
+  kwsysProcess_Option_Verbatim,
+  kwsysProcess_Option_CreateProcessGroup
 };
 
 /**
@@ -362,6 +374,17 @@ enum kwsysProcess_Pipes_e
  */
 kwsysEXPORT int kwsysProcess_WaitForExit(kwsysProcess* cp, double* timeout);
 
+/**
+ * Interrupt the process group for the child process that is currently
+ * running by sending it the appropriate operating-system specific signal.
+ * The caller should call WaitForExit after this returns to wait for the
+ * child to terminate.
+ *
+ * WARNING:  If you didn't specify kwsysProcess_Option_CreateProcessGroup,
+ * you will interrupt your own process group.
+ */
+kwsysEXPORT void kwsysProcess_Interrupt(kwsysProcess* cp);
+
 /**
  * Forcefully terminate the child process that is currently running.
  * The caller should call WaitForExit after this returns to wait for
@@ -394,6 +417,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
 #  undef kwsysProcess_Option_HideWindow
 #  undef kwsysProcess_Option_MergeOutput
 #  undef kwsysProcess_Option_Verbatim
+#  undef kwsysProcess_Option_CreateProcessGroup
 #  undef kwsysProcess_GetOption
 #  undef kwsysProcess_SetOption
 #  undef kwsysProcess_Option_e
@@ -430,6 +454,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
 #  undef kwsysProcess_Pipe_Timeout
 #  undef kwsysProcess_Pipe_Handle
 #  undef kwsysProcess_WaitForExit
+#  undef kwsysProcess_Interrupt
 #  undef kwsysProcess_Kill
 # endif
 #endif
diff --git a/ProcessUNIX.c b/ProcessUNIX.c
index 8c2b2e4633b734284016cb73f22dd9b556de7938..9b6edfc7fd7b4b3b4af62e9620b890c96838f0f8 100644
--- a/ProcessUNIX.c
+++ b/ProcessUNIX.c
@@ -151,6 +151,7 @@ typedef struct kwsysProcessCreateInformation_s
 } kwsysProcessCreateInformation;
 
 /*--------------------------------------------------------------------------*/
+static void kwsysProcessVolatileFree(volatile void* p);
 static int kwsysProcessInitialize(kwsysProcess* cp);
 static void kwsysProcessCleanup(kwsysProcess* cp, int error);
 static void kwsysProcessCleanupDescriptor(int* pfd);
@@ -197,7 +198,7 @@ struct kwsysProcess_s
 {
   /* The command lines to execute.  */
   char*** Commands;
-  int NumberOfCommands;
+  volatile int NumberOfCommands;
 
   /* Descriptors for the read ends of the child's output pipes and
      the signal pipe. */
@@ -213,8 +214,10 @@ struct kwsysProcess_s
   /* Buffer for pipe data.  */
   char PipeBuffer[KWSYSPE_PIPE_BUFFER_SIZE];
 
-  /* Process IDs returned by the calls to fork.  */
-  pid_t* ForkPIDs;
+  /* Process IDs returned by the calls to fork.  Everything is volatile
+     because the signal handler accesses them.  You must be very careful
+     when reaping PIDs or modifying this array to avoid race conditions.  */
+  volatile pid_t* volatile ForkPIDs;
 
   /* Flag for whether the children were terminated by a faild select.  */
   int SelectError;
@@ -237,6 +240,9 @@ struct kwsysProcess_s
   /* Whether to merge stdout/stderr of the child.  */
   int MergeOutput;
 
+  /* Whether to create the process in a new process group.  */
+  volatile sig_atomic_t CreateProcessGroup;
+
   /* Time at which the child started.  Negative for no timeout.  */
   kwsysProcessTime StartTime;
 
@@ -257,8 +263,9 @@ struct kwsysProcess_s
   /* The number of children still executing.  */
   int CommandsLeft;
 
-  /* The current status of the child process. */
-  int State;
+  /* The current status of the child process.  Must be atomic because
+     the signal handler checks this to avoid a race.  */
+  volatile sig_atomic_t State;
 
   /* The exceptional behavior that terminated the child process, if
    * any.  */
@@ -271,7 +278,7 @@ struct kwsysProcess_s
   int ExitValue;
 
   /* Whether the process was killed.  */
-  int Killed;
+  volatile sig_atomic_t Killed;
 
   /* Buffer for error message in case of failure.  */
   char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
@@ -649,6 +656,8 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
     case kwsysProcess_Option_Detach: return cp->OptionDetach;
     case kwsysProcess_Option_MergeOutput: return cp->MergeOutput;
     case kwsysProcess_Option_Verbatim: return cp->Verbatim;
+    case kwsysProcess_Option_CreateProcessGroup:
+      return cp->CreateProcessGroup;
     default: return 0;
     }
 }
@@ -666,6 +675,8 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
     case kwsysProcess_Option_Detach: cp->OptionDetach = value; break;
     case kwsysProcess_Option_MergeOutput: cp->MergeOutput = value; break;
     case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break;
+    case kwsysProcess_Option_CreateProcessGroup:
+      cp->CreateProcessGroup = value; break;
     default: break;
     }
 }
@@ -1489,6 +1500,45 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
   return 1;
 }
 
+/*--------------------------------------------------------------------------*/
+void kwsysProcess_Interrupt(kwsysProcess* cp)
+{
+  int i;
+  /* Make sure we are executing a process.  */
+  if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired ||
+     cp->Killed)
+    {
+    return;
+    }
+
+  /* Interrupt the children.  */
+  if (cp->CreateProcessGroup)
+    {
+    if(cp->ForkPIDs)
+      {
+      for(i=0; i < cp->NumberOfCommands; ++i)
+        {
+        /* Make sure the PID is still valid. */
+        if(cp->ForkPIDs[i])
+          {
+          /* The user created a process group for this process.  The group ID
+             is the process ID for the original process in the group.  */
+          kill(-cp->ForkPIDs[i], SIGINT);
+          }
+        }
+      }
+    }
+  else
+    {
+    /* No process group was created.  Kill our own process group.
+       NOTE:  While one could argue that we could call kill(cp->ForkPIDs[i],
+       SIGINT) as a way to still interrupt the process even though it's not in
+       a special group, this is not an option on Windows.  Therefore, we kill
+       the current process group for consistency with Windows.  */
+    kill(0, SIGINT);
+    }
+}
+
 /*--------------------------------------------------------------------------*/
 void kwsysProcess_Kill(kwsysProcess* cp)
 {
@@ -1538,11 +1588,29 @@ void kwsysProcess_Kill(kwsysProcess* cp)
   cp->CommandsLeft = 0;
 }
 
+/*--------------------------------------------------------------------------*/
+/* Call the free() function with a pointer to volatile without causing
+   compiler warnings.  */
+static void kwsysProcessVolatileFree(volatile void* p)
+{
+  /* clang has made it impossible to free memory that points to volatile
+     without first using special pragmas to disable a warning...  */
+#if defined(__clang__)
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wcast-qual"
+#endif
+  free((void*)p); /* The cast will silence most compilers, but not clang.  */
+#if defined(__clang__)
+# pragma clang diagnostic pop
+#endif
+}
+
 /*--------------------------------------------------------------------------*/
 /* Initialize a process control structure for kwsysProcess_Execute.  */
 static int kwsysProcessInitialize(kwsysProcess* cp)
 {
   int i;
+  volatile pid_t* oldForkPIDs;
   for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
     {
     cp->PipeReadEnds[i] = -1;
@@ -1571,16 +1639,21 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
   cp->ErrorMessage[0] = 0;
   strcpy(cp->ExitExceptionString, "No exception");
 
-  if(cp->ForkPIDs)
+  oldForkPIDs = cp->ForkPIDs;
+  cp->ForkPIDs = (volatile pid_t*)malloc(
+    sizeof(volatile pid_t)*(size_t)(cp->NumberOfCommands));
+  if(oldForkPIDs)
     {
-    free(cp->ForkPIDs);
+    kwsysProcessVolatileFree(oldForkPIDs);
     }
-  cp->ForkPIDs = (pid_t*)malloc(sizeof(pid_t)*(size_t)(cp->NumberOfCommands));
   if(!cp->ForkPIDs)
     {
     return 0;
     }
-  memset(cp->ForkPIDs, 0, sizeof(pid_t)*(size_t)(cp->NumberOfCommands));
+  for(i=0; i < cp->NumberOfCommands; ++i)
+    {
+    cp->ForkPIDs[i] = 0; /* can't use memset due to volatile */
+    }
 
   if(cp->CommandExitCodes)
     {
@@ -1671,7 +1744,7 @@ static void kwsysProcessCleanup(kwsysProcess* cp, int error)
   /* Free memory.  */
   if(cp->ForkPIDs)
     {
-    free(cp->ForkPIDs);
+    kwsysProcessVolatileFree(cp->ForkPIDs);
     cp->ForkPIDs = 0;
     }
   if(cp->RealWorkingDirectory)
@@ -1758,15 +1831,49 @@ int decc$set_child_standard_streams(int fd1, int fd2, int fd3);
 static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
                               kwsysProcessCreateInformation* si)
 {
+  sigset_t mask, old_mask;
+  int pgidPipe[2];
+  char tmp;
+  ssize_t readRes;
+
   /* Create the error reporting pipe.  */
   if(pipe(si->ErrorPipe) < 0)
     {
     return 0;
     }
 
-  /* Set close-on-exec flag on the error pipe's write end.  */
-  if(fcntl(si->ErrorPipe[1], F_SETFD, FD_CLOEXEC) < 0)
+  /* Create a pipe for detecting that the child process has created a process
+     group and session.  */
+  if(pipe(pgidPipe) < 0)
     {
+    kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+    kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
+    return 0;
+    }
+
+  /* Set close-on-exec flag on the pipe's write end.  */
+  if(fcntl(si->ErrorPipe[1], F_SETFD, FD_CLOEXEC) < 0 ||
+     fcntl(pgidPipe[1], F_SETFD, FD_CLOEXEC) < 0)
+    {
+    kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+    kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
+    kwsysProcessCleanupDescriptor(&pgidPipe[0]);
+    kwsysProcessCleanupDescriptor(&pgidPipe[1]);
+    return 0;
+    }
+
+  /* Block SIGINT / SIGTERM while we start.  The purpose is so that our signal
+     handler doesn't get called from the child process after the fork and
+     before the exec, and subsequently start kill()'ing PIDs from ForkPIDs. */
+  sigemptyset(&mask);
+  sigaddset(&mask, SIGINT);
+  sigaddset(&mask, SIGTERM);
+  if(sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0)
+    {
+    kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+    kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
+    kwsysProcessCleanupDescriptor(&pgidPipe[0]);
+    kwsysProcessCleanupDescriptor(&pgidPipe[1]);
     return 0;
     }
 
@@ -1774,13 +1881,19 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
 #if defined(__VMS)
   /* VMS needs vfork and execvp to be in the same function because
      they use setjmp/longjmp to run the child startup code in the
-     parent!  TODO: OptionDetach.  */
+     parent!  TODO: OptionDetach.  Also
+     TODO:  CreateProcessGroup.  */
   cp->ForkPIDs[prIndex] = vfork();
 #else
   cp->ForkPIDs[prIndex] = kwsysProcessFork(cp, si);
 #endif
   if(cp->ForkPIDs[prIndex] < 0)
     {
+    sigprocmask(SIG_SETMASK, &old_mask, 0);
+    kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+    kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
+    kwsysProcessCleanupDescriptor(&pgidPipe[0]);
+    kwsysProcessCleanupDescriptor(&pgidPipe[1]);
     return 0;
     }
 
@@ -1790,8 +1903,10 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
     /* Specify standard pipes for child process.  */
     decc$set_child_standard_streams(si->StdIn, si->StdOut, si->StdErr);
 #else
-    /* Close the read end of the error reporting pipe.  */
+    /* Close the read end of the error reporting / process group
+       setup pipe.  */
     close(si->ErrorPipe[0]);
+    close(pgidPipe[0]);
 
     /* Setup the stdin, stdout, and stderr pipes.  */
     if(si->StdIn > 0)
@@ -1819,11 +1934,25 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
 
     /* Restore all default signal handlers. */
     kwsysProcessRestoreDefaultSignalHandlers();
+
+    /* Now that we have restored default signal handling and created the
+       process group, restore mask.  */
+    sigprocmask(SIG_SETMASK, &old_mask, 0);
+
+    /* Create new process group.  We use setsid instead of setpgid to avoid
+       the child getting hung up on signals like SIGTTOU.  (In the real world,
+       this has been observed where "git svn" ends up calling the "resize"
+       program which opens /dev/tty.  */
+    if(cp->CreateProcessGroup && setsid() < 0)
+      {
+      kwsysProcessChildErrorExit(si->ErrorPipe[1]);
+      }
 #endif
 
     /* Execute the real process.  If successful, this does not return.  */
     execvp(cp->Commands[prIndex][0], cp->Commands[prIndex]);
     /* TODO: What does VMS do if the child fails to start?  */
+    /* TODO: On VMS, how do we put the process in a new group?  */
 
     /* Failure.  Report error to parent and terminate.  */
     kwsysProcessChildErrorExit(si->ErrorPipe[1]);
@@ -1834,12 +1963,33 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
   decc$set_child_standard_streams(0, 1, 2);
 #endif
 
+  /* We are done with the error reporting pipe and process group setup pipe
+     write end.  */
+  kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
+  kwsysProcessCleanupDescriptor(&pgidPipe[1]);
+
+  /* Make sure the child is in the process group before we proceed.  This
+     avoids race conditions with calls to the kill function that we make for
+     signalling process groups.  */
+  while((readRes = read(pgidPipe[0], &tmp, 1)) > 0);
+  if(readRes < 0)
+    {
+    sigprocmask(SIG_SETMASK, &old_mask, 0);
+    kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+    kwsysProcessCleanupDescriptor(&pgidPipe[0]);
+    return 0;
+    }
+
+  /* Unmask signals.  */
+  if(sigprocmask(SIG_SETMASK, &old_mask, 0) < 0)
+    {
+    kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
+    return 0;
+    }
+
   /* A child has been created.  */
   ++cp->CommandsLeft;
 
-  /* We are done with the error reporting pipe write end.  */
-  kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
-
   /* Block until the child's exec call succeeds and closes the error
      pipe or writes data to the pipe to report an error.  */
   {
@@ -1877,6 +2027,17 @@ static void kwsysProcessDestroy(kwsysProcess* cp)
   /* A child process has terminated.  Reap it if it is one handled by
      this object.  */
   int i;
+  /* Temporarily disable signals that access ForkPIDs.  We don't want them to
+     read a reaped PID, and writes to ForkPIDs are not atomic.  */
+  sigset_t mask, old_mask;
+  sigemptyset(&mask);
+  sigaddset(&mask, SIGINT);
+  sigaddset(&mask, SIGTERM);
+  if(sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0)
+    {
+    return;
+    }
+
   for(i=0; i < cp->NumberOfCommands; ++i)
     {
     if(cp->ForkPIDs[i])
@@ -1910,6 +2071,9 @@ static void kwsysProcessDestroy(kwsysProcess* cp)
         }
       }
     }
+
+  /* Re-enable signals.  */
+  sigprocmask(SIG_SETMASK, &old_mask, 0);
 }
 
 /*--------------------------------------------------------------------------*/
@@ -2590,13 +2754,15 @@ static struct sigaction kwsysProcessesOldSigTermAction;
 /*--------------------------------------------------------------------------*/
 static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses)
 {
-  /* Block SIGCHLD while we update the set of pipes to check.
+  /* Block signals while we update the set of pipes to check.
      TODO: sigprocmask is undefined for threaded apps.  See
      pthread_sigmask.  */
   sigset_t newset;
   sigset_t oldset;
   sigemptyset(&newset);
   sigaddset(&newset, SIGCHLD);
+  sigaddset(&newset, SIGINT);
+  sigaddset(&newset, SIGTERM);
   sigprocmask(SIG_BLOCK, &newset, &oldset);
 
   /* Store the new set in that seen by the signal handler.  */
@@ -2784,7 +2950,7 @@ static void kwsysProcessesSignalHandler(int signum
 #endif
   )
 {
-  int i, procStatus, old_errno = errno;
+  int i, j, procStatus, old_errno = errno;
 #if KWSYSPE_USE_SIGINFO
   (void)info;
   (void)ucontext;
@@ -2808,10 +2974,34 @@ static void kwsysProcessesSignalHandler(int signum
       break;
     case SIGINT:
     case SIGTERM:
+      /* Signal child processes that are running in new process groups.  */
+      for(i=0; i < kwsysProcesses.Count; ++i)
+        {
+        kwsysProcess* cp = kwsysProcesses.Processes[i];
+        /* Check Killed to avoid data race condition when killing.
+           Check State to avoid data race condition in kwsysProcessCleanup
+           when there is an error (it leaves a reaped PID).  */
+        if(cp->CreateProcessGroup && !cp->Killed &&
+           cp->State != kwsysProcess_State_Error && cp->ForkPIDs)
+          {
+          for(j=0; j < cp->NumberOfCommands; ++j)
+            {
+            /* Make sure the PID is still valid. */
+            if(cp->ForkPIDs[j])
+              {
+              /* The user created a process group for this process.  The group ID
+                 is the process ID for the original process in the group.  */
+              kill(-cp->ForkPIDs[j], SIGINT);
+              }
+            }
+          }
+        }
+
       /* Wait for all processes to terminate.  */
       while(wait(&procStatus) >= 0 || errno != ECHILD)
         {
         }
+
       /* Terminate the process, which is now in an inconsistent state
          because we reaped all the PIDs that it may have been reaping
          or may have reaped in the future.  Reraise the signal so that
diff --git a/ProcessWin32.c b/ProcessWin32.c
index 086fc391c3157be9ece056777b7f5078e87b4942..ba3397c52fc4bcd78311fe6782525cb0f89c0b4c 100644
--- a/ProcessWin32.c
+++ b/ProcessWin32.c
@@ -136,7 +136,8 @@ static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
 static int kwsysProcessesInitialize(void);
 static int kwsysTryEnterCreateProcessSection(void);
 static void kwsysLeaveCreateProcessSection(void);
-static int kwsysProcessesAdd(HANDLE hProcess);
+static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessId,
+                             int newProcessGroup);
 static void kwsysProcessesRemove(HANDLE hProcess);
 static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType);
 
@@ -228,6 +229,9 @@ struct kwsysProcess_s
   /* Whether to merge stdout/stderr of the child.  */
   int MergeOutput;
 
+  /* Whether to create the process in a new process group.  */
+  int CreateProcessGroup;
+
   /* Mutex to protect the shared index used by threads to report data.  */
   HANDLE SharedIndexMutex;
 
@@ -852,6 +856,8 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
     case kwsysProcess_Option_HideWindow: return cp->HideWindow;
     case kwsysProcess_Option_MergeOutput: return cp->MergeOutput;
     case kwsysProcess_Option_Verbatim: return cp->Verbatim;
+    case kwsysProcess_Option_CreateProcessGroup:
+      return cp->CreateProcessGroup;
     default: return 0;
     }
 }
@@ -870,6 +876,8 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
     case kwsysProcess_Option_HideWindow: cp->HideWindow = value; break;
     case kwsysProcess_Option_MergeOutput: cp->MergeOutput = value; break;
     case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break;
+    case kwsysProcess_Option_CreateProcessGroup:
+      cp->CreateProcessGroup = value; break;
     default: break;
     }
 }
@@ -1475,6 +1483,52 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
   return 1;
 }
 
+/*--------------------------------------------------------------------------*/
+void kwsysProcess_Interrupt(kwsysProcess* cp)
+{
+  int i;
+  /* Make sure we are executing a process.  */
+  if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired ||
+     cp->Killed)
+    {
+    KWSYSPE_DEBUG((stderr, "interrupt: child not executing\n"));
+    return;
+    }
+
+  /* Skip actually interrupting the child if it has already terminated.  */
+  if(cp->Terminated)
+    {
+    KWSYSPE_DEBUG((stderr, "interrupt: child already terminated\n"));
+    return;
+    }
+
+  /* Interrupt the children.  */
+  if (cp->CreateProcessGroup)
+    {
+    if(cp->ProcessInformation)
+      {
+      for(i=0; i < cp->NumberOfCommands; ++i)
+        {
+        /* Make sure the process handle isn't closed (e.g. from disowning). */
+        if(cp->ProcessInformation[i].hProcess)
+          {
+          /* The user created a process group for this process.  The group ID
+             is the process ID for the original process in the group.  Note
+             that we have to use Ctrl+Break: Ctrl+C is not allowed for process
+             groups.  */
+          GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT,
+                                   cp->ProcessInformation[i].dwProcessId);
+          }
+        }
+      }
+    }
+  else
+    {
+    /* No process group was created.  Kill our own process group...  */
+    GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);
+    }
+}
+
 /*--------------------------------------------------------------------------*/
 void kwsysProcess_Kill(kwsysProcess* cp)
 {
@@ -1745,6 +1799,7 @@ static int kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn)
 int kwsysProcessCreate(kwsysProcess* cp, int index,
                        kwsysProcessCreateInformation* si)
 {
+  DWORD creationFlags;
   int res;
 
   /* Check if we are currently exiting.  */
@@ -1757,6 +1812,14 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
     Sleep(INFINITE);
     }
 
+  /* Create the child in a suspended state so we can wait until all
+     children have been created before running any one.  */
+  creationFlags = CREATE_SUSPENDED;
+  if (cp->CreateProcessGroup)
+    {
+    creationFlags |= CREATE_NEW_PROCESS_GROUP;
+    }
+
   res =
 
     /* Create inherited copies the handles.  */
@@ -1767,9 +1830,7 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
     kwsysProcessCreateChildHandle(&si->StartupInfo.hStdError,
                                   si->hStdError, 0) &&
 
-    /* Create the child in a suspended state so we can wait until all
-       children have been created before running any one.  */
-    CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0,
+    CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, creationFlags, 0,
                    0, &si->StartupInfo, &cp->ProcessInformation[index]);
 
   /* Close the inherited copies of the handles. */
@@ -1787,7 +1848,8 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
     }
 
   /* Add the process to the global list of processes. */
-  if (!kwsysProcessesAdd(cp->ProcessInformation[index].hProcess))
+  if (!kwsysProcessesAdd(cp->ProcessInformation[index].hProcess,
+      cp->ProcessInformation[index].dwProcessId, cp->CreateProcessGroup))
     {
     /* This failed for some reason.  Kill the suspended process. */
     TerminateProcess(cp->ProcessInformation[index].hProcess, 1);
@@ -2715,6 +2777,13 @@ static void kwsysProcessDisablePipeThreads(kwsysProcess* cp)
    everything it does must be thread safe.  Here, we track the hProcess
    HANDLEs directly instead of kwsysProcess instances, so that we don't have
    to make kwsysProcess thread safe.  */
+typedef struct kwsysProcessInstance_s
+{
+  HANDLE hProcess;
+  DWORD dwProcessId;
+  int NewProcessGroup; /* Whether the process was created in a new group.  */
+} kwsysProcessInstance;
+
 typedef struct kwsysProcessInstances_s
 {
   /* Whether we have initialized key fields below, like critical sections.  */
@@ -2726,7 +2795,7 @@ typedef struct kwsysProcessInstances_s
   int Exiting;
   size_t Count;
   size_t Size;
-  HANDLE* Processes;
+  kwsysProcessInstance* Processes;
 } kwsysProcessInstances;
 static kwsysProcessInstances kwsysProcesses;
 
@@ -2784,8 +2853,10 @@ static void kwsysLeaveCreateProcessSection(void)
 /*--------------------------------------------------------------------------*/
 /* Add new process to global process list.  The Ctrl handler will wait for
    the process to exit before it returns.  Do not close the process handle
-   until after calling kwsysProcessesRemove.  */
-static int kwsysProcessesAdd(HANDLE hProcess)
+   until after calling kwsysProcessesRemove.  The newProcessGroup parameter
+   must be set if the process was created with CREATE_NEW_PROCESS_GROUP.  */
+static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessid,
+                             int newProcessGroup)
 {
   if(!kwsysProcessesInitialize() || !hProcess ||
       hProcess == INVALID_HANDLE_VALUE)
@@ -2800,19 +2871,20 @@ static int kwsysProcessesAdd(HANDLE hProcess)
   if(kwsysProcesses.Count == kwsysProcesses.Size)
     {
     size_t newSize;
-    HANDLE *newArray;
+    kwsysProcessInstance *newArray;
     /* Start with enough space for a small number of process handles
        and double the size each time more is needed.  */
     newSize = kwsysProcesses.Size? kwsysProcesses.Size*2 : 4;
 
     /* Try allocating the new block of memory.  */
-    if(newArray = (HANDLE*)malloc(newSize*sizeof(HANDLE)))
+    if(newArray = (kwsysProcessInstance*)malloc(
+       newSize*sizeof(kwsysProcessInstance)))
       {
       /* Copy the old process handles to the new memory.  */
       if(kwsysProcesses.Count > 0)
         {
         memcpy(newArray, kwsysProcesses.Processes,
-               kwsysProcesses.Count * sizeof(HANDLE));
+               kwsysProcesses.Count * sizeof(kwsysProcessInstance));
         }
       }
     else
@@ -2830,8 +2902,11 @@ static int kwsysProcessesAdd(HANDLE hProcess)
     kwsysProcesses.Processes = newArray;
     }
 
-  /* Append the new process handle to the set.  */
-  kwsysProcesses.Processes[kwsysProcesses.Count++] = hProcess;
+  /* Append the new process information to the set.  */
+  kwsysProcesses.Processes[kwsysProcesses.Count].hProcess = hProcess;
+  kwsysProcesses.Processes[kwsysProcesses.Count].dwProcessId = dwProcessid;
+  kwsysProcesses.Processes[kwsysProcesses.Count++].NewProcessGroup =
+    newProcessGroup;
 
   /* Leave critical section and return success. */
   LeaveCriticalSection(&kwsysProcesses.Lock);
@@ -2855,7 +2930,7 @@ static void kwsysProcessesRemove(HANDLE hProcess)
   /* Find the given process in the set.  */
   for(i=0; i < kwsysProcesses.Count; ++i)
     {
-    if(kwsysProcesses.Processes[i] == hProcess)
+    if(kwsysProcesses.Processes[i].hProcess == hProcess)
       {
       break;
       }
@@ -2884,6 +2959,7 @@ static void kwsysProcessesRemove(HANDLE hProcess)
 /*--------------------------------------------------------------------------*/
 static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType)
 {
+  size_t i;
   (void)dwCtrlType;
   /* Enter critical section.  */
   EnterCriticalSection(&kwsysProcesses.Lock);
@@ -2891,13 +2967,26 @@ static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType)
   /* Set flag indicating that we are exiting.  */
   kwsysProcesses.Exiting = 1;
 
+  /* If some of our processes were created in a new process group, we must
+     manually interrupt them.  They won't otherwise receive a Ctrl+C/Break. */
+  for(i=0; i < kwsysProcesses.Count; ++i)
+    {
+    if(kwsysProcesses.Processes[i].NewProcessGroup)
+      {
+      DWORD groupId = kwsysProcesses.Processes[i].dwProcessId;
+      if(groupId)
+        {
+        GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, groupId);
+        }
+      }
+    }
+
   /* Wait for each child process to exit.  This is the key step that prevents
      us from leaving several orphaned children processes running in the
      background when the user presses Ctrl+C.  */
-  if(kwsysProcesses.Count > 0) /* WaitForMultipleObjects forbids Count==0.  */
+  for(i=0; i < kwsysProcesses.Count; ++i)
     {
-    WaitForMultipleObjects((DWORD)kwsysProcesses.Count,
-                           kwsysProcesses.Processes, TRUE, INFINITE);
+    WaitForSingleObject(kwsysProcesses.Processes[i].hProcess, INFINITE);
     }
 
   /* Leave critical section.  */