Subject: cygwin 1.3.10 mmap+fork+sockets=fixup_mmaps_after_fork
From: Michael Potter <[email-masked]>
To: [email-masked]
Date: Mon, 3 Jun 2002 15:57:07 -0500 (CDT)

Enclosed is a sample program that demonstrates a bug with
mmap, fork, and sockets.  This sample is very similar to
on submitted by me on june 2, but this one eliminiates sysV ipc.

here is the sample run:

 [@TERMSERV]/cygdrive/c/apps/apwin1/src/forktest>
-> gcc -oforktest2 forktest2.c
 [@TERMSERV]/cygdrive/c/apps/apwin1/src/forktest>
-> ./forktest2
in pid = 2276
entering NetWorkSocket
Port=5210, Socket=3, sinport=23060
exiting NetWorkSocket
entering accept
 [@TERMSERV]/cygdrive/c/apps/apwin1/src/forktest>
-> after accept
in pid = 6880
   1963 [main] forktest2 7220 fixup_mmaps_after_fork: base address fails to matc
h requested address 0x650000
c:\apps\apwin1\src\forktest\forktest2.exe: *** recreate_mmaps_after_fork_failed

Note: you have to telnet to port 5210 to allow the program to continue.

----------------------------------------------------------------------
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#  include <unistd.h>
#  include <sys/mman.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>

static int RegProcNet_sd;
static struct sockaddr_in Sin;
static const int on = 1;

int SwitchToPrivate_sd(void)
{
   int NewNet_sd;
   unsigned long SizeOfsockaddr_in = sizeof (struct sockaddr_in);

   printf("entering accept\n");
   NewNet_sd = accept(RegProcNet_sd, (struct sockaddr *)&Sin,
    (size_t *)&SizeOfsockaddr_in);

   printf("after accept\n");

   if (NewNet_sd < 0)
   {
      int SaveErrNo = errno;
      printf("Exiting due to error in accept %d\n", SaveErrNo);
      exit(1);
   }
   return(NewNet_sd);
}

#define PORT_NUM 5210

void NetWorkSocket(void)
{

   int SizeOfsockaddr_in = sizeof (struct sockaddr_in);
   bzero((char *) &Sin, sizeof(Sin));
   Sin.sin_family = AF_INET; 
   Sin.sin_addr.s_addr = htonl(INADDR_ANY) ;
   Sin.sin_port = htons((unsigned short)PORT_NUM);

   printf("entering NetWorkSocket\n");

   RegProcNet_sd = socket(AF_INET, SOCK_STREAM, 0);
   if (RegProcNet_sd < 0)
   {
      int SaveErrNo = errno;
      printf("Exiting due to error in socket %d\n", SaveErrNo);
      exit(1);
   }
   
   (void) setsockopt(RegProcNet_sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
   
   if (bind(RegProcNet_sd, (struct sockaddr *)&Sin, SizeOfsockaddr_in) < 0)
   {
      int SaveErrNo = errno;
      printf("Exiting due to error in bind %d\n", SaveErrNo);
      exit(1);
   }

   if (listen(RegProcNet_sd, 1) < 0)
   {
      int SaveErrNo = errno;
      printf("Exiting due to error in listen %d\n", SaveErrNo);
      exit(1);
   }
   {
      printf("Port=%d, Socket=%d, sinport=%d\n",
                              PORT_NUM, RegProcNet_sd, Sin.sin_port);
   }
   printf("exiting NetWorkSocket\n");
   return;
}

int main(int argc, char *argv[])
{
   char *shmptr3;
   int SaveErrno;
   int sd;

   if (fork())
   {
      printf("in pid = %d\n", getpid());
      exit(0);
   }

   shmptr3 = mmap(0, 1024*1024, PROT_READ|PROT_WRITE,
                            MAP_ANONYMOUS|MAP_SHARED, -1, 0);

   if (shmptr3 == (char *)-1)
   {
      SaveErrno = errno;
      printf("mmap failed errno = %d\n", SaveErrno);
      exit(1);
   }

   NetWorkSocket();

   sd = SwitchToPrivate_sd();

   fork();
   printf("in pid = %d\n", getpid());
   exit(0);
}
----------------------------------------------------------------------

-- 
Michael Potter

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/