make-w32
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: make 3.81 and MS-DOS paths (e.g. C: or drive letter paths)


From: Brian Dessent
Subject: Re: make 3.81 and MS-DOS paths (e.g. C: or drive letter paths)
Date: Thu, 03 Jul 2008 11:38:58 -0700

Paul Smith wrote:

> Make jobserver doesn't use named pipes, at least not on POSIX systems.
> It does, however, require fully capable POSIX pipes, in particular ones
> that are inherited by/shared across multiple processes and which can be
> read from and written to by multiple processes simultaneously.

That should be no problem for Win32.  The attached testcase sets up a
pipe and then spawns NCHILD children who each write NMSG messages to the
pipe, which are read and printed by the parent, resulting in e.g.

message #0 from child 3770
message #1 from child 3770
message #0 from child 3968
message #1 from child 3968
message #0 from child 3f68
message #2 from child 3770
message #2 from child 3968
message #1 from child 3f68
message #2 from child 3f68
All children exited; done.

The only bit of subtlety that I can see has to do with the inheritance
flag on each HANDLE.  The MSDN docs communicate the idea that parent and
child should each have only one end open, i.e. that only half of the
pipe pair should be inherited.  In this testcase I did not bother doing
that and it seems to work fine, but if this is necessary it can be done
easily by adding _O_NOINHERIT to the third argument of _pipe() followed
by setting the inherit flag on the write end with:

 if (!SetHandleInformation ((HANDLE) _get_osfhandle (pipefds[1]),
      HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
   /* error */

This has the downside that SetHandleInformation() is not available on
9x/ME but only NT/2K/XP and later.  If compatibility with these old
systems is required, the inheritance can be set with DuplicateHandle()
and a little more legwork.

Brian
#include <io.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <windows.h>

#define NMSG 3
#define NCHILD 3

int main (int argc, char **argv)
{
  char buf[512];
  int i;

  if (argc == 1)
    {
      /* No args, we are the parent.  */
      int pipefds[2];

      if (_pipe (pipefds, 512, _O_BINARY) < 0)
        {
          perror ("pipe");
          exit (1);
        }

      /* Spawn some children.  */
      itoa (pipefds[1], buf, 10);
      for (i = 0; i < NCHILD; i++)
        {
          if (spawnl (_P_NOWAIT, argv[0], argv[0], buf, NULL) < 0)
            {
              perror ("spawnl");
              exit (1);
            }
        }

      /* Read their messages.  */
      int donecount = 0, lenread;
      while ((lenread = read (pipefds[0], buf, sizeof (buf))) > 0)
        {
          if (memcmp (buf, "done\n", 5) == 0)
            {
              if (++donecount == NCHILD)
                {
                  puts ("All children exited; done.\n");
                  exit (0);
                }
            }
          else
            {
              if (write (1, buf, lenread) < 0)
                {
                  perror ("write");
                  exit (1);
                }
            }
        }
    }
  else
    {
      /* We are the child.  The argument is the fd to write to.  */
      int pipewrite = atoi (argv[1]);

      srand (getpid () * time (NULL));
      for (i = 0; i < NMSG + 1; i++)
        {
          Sleep (((double) rand () / (double) RAND_MAX) * 500.0);
          if (i != NMSG)
            sprintf (buf, "message #%d from child %x\n", i, getpid ());
          else
            strcpy (buf, "done\n");
          if (write (pipewrite, buf, strlen (buf)) < 0)
            {
              perror ("write");
              exit (1);
            }
        }
    }
  return 0;
}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]