Subject: None
To: None <netbsd-bugs@NetBSD.ORG>
From: None <robin@red-branch.MIT.EDU>
List: netbsd-bugs
Date: 03/19/1995 14:23:56
My system is NetBSD-1.0/i386 binary w/o patches. I've discovered what appears
to be a bug with regard to SOL_SOCKET options, after a call to fork(2)
has been made. The following typescript illustrates the problem, that
after a call to fork(), an fd inherited from the parent process does not
retain its SOL_SOCKET SO_TYPE. I've tried the code on Soaris System V, which
managed to find the type of the socket only in the forked image and not in the
parent ! However it worked as it should do on DYNIX.

----->----->---->

Script started on Sun Mar 19 18:23:13 1995
bash$ cat mother.c
#include  <errno.h>
#include  <limits.h>
#include  <stdarg.h>
#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>

#include  <sys/types.h>
#include  <sys/socket.h>
#include  <unistd.h>

#define  IPC_PIPE(sv)           (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, (sv)))
#define  WARN(x)                (Log("WARNING: [%s:%d] %s: %s", __FILE__, __LINE__, (x), strerror(errno)))


static void
Log(const char *fmt,...)
{
  va_list                         ap;
  char                            buf[2048];

  va_start(ap, fmt);
  /* This is NOT safe, but vsnprintf(3) is not ``ANSI C'' ! */
  vsprintf(buf, fmt, ap);
  va_end(ap);

  fprintf(stderr, "[mother] %s\n", buf);
  fflush(stderr);
}

static void
List(void)
{
  register int                    i;
  int                             type;
  int                             size;

  for (i = 0; i < OPEN_MAX; ++i)
    if (getsockopt(i, SOL_SOCKET, SO_TYPE, &type, &size) != -1)
      Log("FD: #%d, TYPE: %d, SIZE: %d", i, type, size);
}

static const int
Fork_and_exec(char *const path)
{
  const pid_t                     child_pid = fork();

  if (child_pid < 0) {
    WARN("fork(2)");
    return -1;
  }
  List();
  if (child_pid == 0) {
    char                           *const argv[] = {path, NULL};
    char                           *const envp[] = {NULL};

    if (execve(path, argv, envp) < 0) {
      WARN("execve(2)");
      exit(EXIT_FAILURE);
    }
  }
  Log("CHILD FORKED: %d", child_pid);
  return child_pid;
}

void
main(int argc, char *argv[])
{
  int                             sockets[2];

  if (argc != 2) {
    Log("Usage: %s <path>", argv[0]);
    exit(EXIT_FAILURE);
  }
  if (IPC_PIPE(&sockets[0]) < 0) {
    WARN("socketpair(2)");
    exit(EXIT_FAILURE);
  }
  List();
  if (Fork_and_exec(argv[1]) < 0) {
    exit(EXIT_FAILURE);
  }
  sleep(3);
  exit(EXIT_SUCCESS);
}
bash$ cay t tablelist.c
#include  <stdio.h>
#include  <limits.h>
#include  <signal.h>
#include  <stdlib.h>

#include  <unistd.h>
#include  <sys/types.h>
#include  <sys/socket.h>

static void
List(void)
{
  register int                    i;
  int                             type;
  int                             size;

  for (i = 0; i < OPEN_MAX; ++i) {
    printf("%d ", i);
    if (getsockopt(i, SOL_SOCKET, SO_TYPE, &type, &size) != -1)
      printf("[TABLELIST] FD: #%d, TYPE: %d, SIZE: %d\n", i, type, size);
  }
  printf("\n");
}

void
main(void)
{
  printf("[TABLELIST] Searching ...\n");
  List();
  exit(EXIT_SUCCESS);
}
bash$ b mother tablelist
[mother] FD: #3, TYPE: 1, SIZE: 1
[mother] FD: #4, TYPE: 1, SIZE: 1
[TABLELIST] Searching ...
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 
[mother] CHILD FORKED: 223
bash$ exit

Script done on Sun Mar 19 18:23:31 1995
<----<-----<----

Any ideas ?
Cheers :)

--
Robin J F Carey