[Cmake-commits] [cmake-commits] king committed ProcessUNIX.c 1.83 1.84

cmake-commits at cmake.org cmake-commits at cmake.org
Wed Jun 10 11:48:37 EDT 2009


Update of /cvsroot/CMake/CMake/Source/kwsys
In directory public:/mounts/ram/cvs-serv31713/Source/kwsys

Modified Files:
	ProcessUNIX.c 
Log Message:
ENH: Teach KWSys Process basic VMS support

This achieves basic process execution on OpenVMS.  We use work-arounds
for different fork()/exec() behavior and a lack of select().

VMS emulates fork/exec using setjmp/longjmp to evaluate the child and
parent return cases from fork.  Therefore both must be invoked from the
same function.

Since select() works only for sockets we use the BeOS-style polling
implementation.  However, non-blocking reads on empty pipes cannot be
distinguished easily from the last read on a closed pipe.  Therefore we
identify end of data by an empty read after the child terminates.


Index: ProcessUNIX.c
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/kwsys/ProcessUNIX.c,v
retrieving revision 1.83
retrieving revision 1.84
diff -C 2 -d -r1.83 -r1.84
*** ProcessUNIX.c	10 Jun 2009 15:46:21 -0000	1.83
--- ProcessUNIX.c	10 Jun 2009 15:48:34 -0000	1.84
***************
*** 68,71 ****
--- 68,77 ----
  #endif
  
+ #if defined(__VMS)
+ # define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK
+ #else
+ # define KWSYSPE_VMS_NONBLOCK
+ #endif
+ 
  #if defined(KWSYS_C_HAS_PTRDIFF_T) && KWSYS_C_HAS_PTRDIFF_T
  typedef ptrdiff_t kwsysProcess_ptrdiff_t;
***************
*** 101,105 ****
   * without select().
   */
! #if !defined(__BEOS__)
  # define KWSYSPE_USE_SELECT 1
  #endif
--- 107,111 ----
   * without select().
   */
! #if !defined(__BEOS__) && !defined(__VMS)
  # define KWSYSPE_USE_SELECT 1
  #endif
***************
*** 171,174 ****
--- 177,181 ----
                                kwsysProcessCreateInformation* si);
  static void kwsysProcessKill(pid_t process_id);
+ static int kwsysProcessSetVMSFeature(char* name, int value);
  static int kwsysProcessesAdd(kwsysProcess* cp);
  static void kwsysProcessesRemove(kwsysProcess* cp);
***************
*** 721,724 ****
--- 728,738 ----
      }
  
+   /* Make sure pipes behave like streams on VMS.  */
+   if(!kwsysProcessSetVMSFeature("DECC$STREAM_PIPE", 1))
+     {
+     kwsysProcessCleanup(cp, 1);
+     return;
+     }
+ 
    /* Save the real working directory of this process and change to
       the working directory for the child processes.  This is needed
***************
*** 760,764 ****
    /* Create the pipe.  */
    int p[2];
!   if(pipe(p) < 0)
      {
      kwsysProcessCleanup(cp, 1);
--- 774,778 ----
    /* Create the pipe.  */
    int p[2];
!   if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0)
      {
      kwsysProcessCleanup(cp, 1);
***************
*** 1186,1194 ****
          {
          /* We are done reading from this pipe.  */
!         kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
!         --cp->PipesLeft;
          }
        else if (n < 0)  /* error */
          {
          if((errno != EINTR) && (errno != EAGAIN))
            {
--- 1200,1221 ----
          {
          /* We are done reading from this pipe.  */
! #if defined(__VMS)
!         if(!cp->CommandsLeft)
! #endif
!           {
!           kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
!           --cp->PipesLeft;
!           }
          }
        else if (n < 0)  /* error */
          {
+ #if defined(__VMS)
+         if(!cp->CommandsLeft)
+           {
+           kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]);
+           --cp->PipesLeft;
+           }
+         else
+ #endif
          if((errno != EINTR) && (errno != EAGAIN))
            {
***************
*** 1567,1570 ****
--- 1594,1602 ----
  
  /*--------------------------------------------------------------------------*/
+ #if defined(__VMS)
+ int decc$set_child_standard_streams(int fd1, int fd2, int fd3);
+ #endif
+ 
+ /*--------------------------------------------------------------------------*/
  static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
                                kwsysProcessCreateInformation* si, int* readEnd)
***************
*** 1617,1621 ****
    /* Create the pipe.  */
    int p[2];
!   if(pipe(p) < 0)
      {
      return 0;
--- 1649,1653 ----
    /* Create the pipe.  */
    int p[2];
!   if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0)
      {
      return 0;
***************
*** 1675,1679 ****
--- 1707,1718 ----
  
    /* Fork off a child process.  */
+ #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.  */
+   cp->ForkPIDs[prIndex] = vfork();
+ #else
    cp->ForkPIDs[prIndex] = kwsysProcessFork(cp, si);
+ #endif
    if(cp->ForkPIDs[prIndex] < 0)
      {
***************
*** 1683,1686 ****
--- 1722,1729 ----
    if(cp->ForkPIDs[prIndex] == 0)
      {
+ #if defined(__VMS)
+     /* 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(si->ErrorPipe[0]);
***************
*** 1712,1718 ****
--- 1755,1763 ----
      /* Restore all default signal handlers. */
      kwsysProcessRestoreDefaultSignalHandlers();
+ #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?  */
  
      /* Failure.  Report error to parent and terminate.  */
***************
*** 1720,1723 ****
--- 1765,1773 ----
      }
  
+ #if defined(__VMS)
+   /* Restore the standard pipes of this process.  */
+   decc$set_child_standard_streams(0, 1, 2);
+ #endif
+ 
    /* A child has been created.  */
    ++cp->CommandsLeft;
***************
*** 2267,2273 ****
      {
      /* Create an intermediate process.  */
- #ifdef __VMS
- #define fork vfork
- #endif
      pid_t middle_pid = fork();
      if(middle_pid < 0)
--- 2317,2320 ----
***************
*** 2438,2441 ****
--- 2485,2508 ----
  
  /*--------------------------------------------------------------------------*/
+ #if defined(__VMS)
+ int decc$feature_get_index(char *name);
+ int decc$feature_set_value(int index, int mode, int value);
+ static int kwsysProcessSetVMSFeature(char* name, int value)
+ {
+   int i;
+   errno = 0;
+   i = decc$feature_get_index(name);
+   return i >= 0 && (decc$feature_set_value(i, 1, value) >= 0 || errno == 0);
+ }
+ #else
+ static int kwsysProcessSetVMSFeature(char* name, int value)
+ {
+   (void)name;
+   (void)value;
+   return 1;
+ }
+ #endif
+ 
+ /*--------------------------------------------------------------------------*/
  /* Global set of executing processes for use by the signal handler.
     This global instance will be zero-initialized by the compiler.  */
***************
*** 2478,2482 ****
    /* Create the pipe.  */
    int p[2];
!   if(pipe(p) < 0)
      {
      return 0;
--- 2545,2549 ----
    /* Create the pipe.  */
    int p[2];
!   if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0)
      {
      return 0;



More information about the Cmake-commits mailing list