[comp.lang.c] Too Many Files Open Error During Shared Memory Attach

staggers@casbah.acns.nwu.edu (Ken Staggers) (06/06/91)

If anybody knows the answer to the problem below, please respond as soon
as possible....thanks a plenty!

The program is basically supposed to schedule running processes.  My main()
uses execution.o to fork and then exec separately compiled programs.  
execution.o issues a SIGSTOP so that main can schedule the processes (i.e.
round robin scheduling).

PCBs, semaphores, buffers, etc are all part of the shared memory that main() and
the separately compiled (and executable) processes can access.  main()
and the processes use a library of system calls (syscall.o) to manipulate
the shared memory.

In my test run, main() creates the shared memory (shmget()), accesses it
(shmget()), and then attaches it (shmat()).  In then intializes all the
structs in shared memory.  This seems to work perfectly.  
Next, main() calls execution() in execution.o to fork and exec the separately
compiled processes.  It fills in a shared memory PCB for each using create()
in syscall.o.  In create(), its possible for one of the separately compiled
processes to want to fork off its own process.  Thus its going to have
to access shared memory.  Thus, in create() I issue an access and then
attach.  Well, I am getting an error in create().  Here's the code:

  /* Access the shared memory segment */
  if ((shmid= shmget((key_t)42, 0, 0)) == -1) {
    printf( "CREATE: Cannot access shared memory segment\n");
    exit(1);
  }

  /* Attach the shared memory segment */
  shm= (struct sharedmemory *) shmat(shmid, (char *)0, 0);
  if (shm == (struct sharedmemory *) -1) {
    perror ("CREATE: Cannot attach the shared memory segment");
    exit(1);
  }

And here is the error:

CREATE: Cannot attach the shared memory segment: Too many open files


Yet, the only open files are main(), its header files, and the separately
complied processes.  I am attempting to schedule 4 processes in my system.
So, I knocked that down to 1 process to see if that would help.  Well, it
did.  Except after exec-ing the one process, it correctly returned to main()
to continue running. I print out the queue, and the process has been
successfully loaded into memory, and the PCB for it has been initialized.
Then I issue a command to print out all of shared memory, to see if everything
has been initialized properly.  Then I get this error from memorydump()
located in syscall.o:

MEMORYDUMP: Cannot attach the shared memory segment: Too many open files

So what am I doing wrong?  Each of the 15 functions in syscall.o has code to
access and attach.  Is this wrong?  I seemed to be able to access, 
but not attach.  WHY?  How does shared memory work?

If you have ANY clues, please let me know as soon AS POSSIBLE.  Since the
program doesnt ever get to the part of removing shared memory, I do it myself
in the shell.

Below is more info on the program.  Any help would be appreciated!

--Ken
  staggers@casbah.acns.nwu.edu

------------------------------------------------------------------------

Shared Memory In globals.h:

struct sharedmemory {
        struct PCB shpcb[MAXPCB]; /* All the PCBs available in system */
        struct semaphore shsema[ MAXSEMAPHORES];
                                 /* Semaphores available in system */
        struct buffer shbuf[MAXBUFFERS];  /* Buffers available in system */
        int Waitflag;            /* Prevents process from being interrupted */
        int Syspid;              /* System pid counter */
        struct PCB shq[ MAXQUEUES+MAXSEMAPHORES]; /* Head of queues */
        int cpu;                 /* Pointer to PCB of running process */
};

struct sharedmemory *shm;        /* Pointer to the shared memory */


Makefile:

CFLAGS=-g

p.out: queue.o syscall.o execution.o p1.o
        cc $(CFLAGS) -o  p.out queue.o syscall.o execution.o p1.o
queue.o: queue.c globals.h
        cc $(CFLAGS) -c queue.c
syscall.o: syscall.c globals.h
        cc $(CFLAGS) -c syscall.c
execution.o: execution.c globals.h
        cc $(CFLAGS) -c execution.c
p1.o: p1.c queue.o globals.h
        cc $(CFLAGS) -c p1.c queue.o

clean:
        rm *.o


Shared Memory Initialization in main() [located in p1.c]:
 (Question: Is create and the access necessary)

  /* Create the shared memory segment */
  if ((shmid= shmget((key_t)42, sizeof(struct sharedmemory),
     (IPC_CREAT | 0666))) == -1) {
    printf( "MAIN: Cannot create shared memory segment\n");
    exit(1);
  }

  /* Access the shared memory segment */
  if ((shmid= shmget((key_t)42, sizeof( struct sharedmemory), 0)) == -1) {
    printf( "MAIN: Cannot access shared memory segment\n");
    exit(1);
  }

  /* Attach the shared memory segment */
  shm= (struct sharedmemory *) shmat(shmid, (char *)0, 0);
  if (shm == (struct sharedmemory *) -1) {
    printf("MAIN: Cannot attach the shared memory segment\n");
    exit(1);
  }

cpcahil@virtech.uucp (Conor P. Cahill) (06/06/91)

staggers@casbah.acns.nwu.edu (Ken Staggers) writes:

>CREATE: Cannot attach the shared memory segment: Too many open files

This is one of the reasons that perror is useless.  "Too many open files"
is the perror output for the errno EMFILE.  Looking up shmat() (on the
shmop(2) manual page) we see:

       [EMFILE]       The number of shared memory segments attached
                      to the calling process would exceed the
                      system-imposed limit.

Depending upon your OS configuration parameters, this should be configurable
with a configuration parameter named SHMSEG (or something similar to it).
-- 
Conor P. Cahill            (703)430-9247        Virtual Technologies, Inc.
uunet!virtech!cpcahil                           46030 Manekin Plaza, Suite 160
                                                Sterling, VA 22170 

scl@unislc.uucp (Sean Landis) (06/08/91)

staggers@casbah.acns.nwu.edu (Ken Staggers) writes:

>If anybody knows the answer to the problem below, please respond as soon
>as possible....thanks a plenty!

> ... Lot's deleted ...

The man page for shmop(2) indicates:


          [EMFILE]       The number of shared memory segments attached
                         to the calling process would exceed the
                         system-imposed limit.

If you look in /usr/include/sys/errno.h:

...
#define EMFILE  24      /* Too many open files                  */
...

Which is what drives perror().  Now what this really means is that your
process is violating a tunable parameter called SHMSEG.  The attachments
are inherited by the forked process that tries to do one more and fails.
Maybe you could do the attach after the exec()?  I know that it removes
some of the object-orientedness from your code, but processes in say
UNIX, do have some startup code in them anyway.

To get a picture of what is going on, use ipcs(1) command to get
interprocess communication status.

Hope this helps,
Sean




-- 
Sean C. Landis                | {hpda, sun, uplherc}!unislc!scl
Unisys Open Systems Group     | unislc!scl@cs.utah.edu
320 North 2200 West B2D01     | (801) 594-3988
Salt Lake City, Utah 84116    | (801) 594-3827 Fax