1

The task was to create simulation of warehouse's work. Producers (in an amount of argv[2]) create random number of "goods" (totally argv[1]), and consumers (in an amount of argv[3]) get random number of these goods. The full code is below. I got segmentation error and tried to debug it and got the following:

Program received signal SIGSEGV, Segmentation fault. __new_sem_init (sem=0x37, pshared=0, value=1) at sem_init.c:44 44 sem_init.c: No such file or directory

I think the problem is in address-of operator here sem_init(&(shared->mutex), 0, 1); How should I change the code to make it work? Thanks a lot!

#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/mman.h>
#define NBUFF 10
#define MAXNTHREADS 100
#define min( a, b ) ( ( a < b) ? a : b ) 
int nitems, nproducers, nconsumers; 

typedef struct shared_s
{ 
    int buff[NBUFF];
    int nput; 
    int nputval; 
    int nget;
    int ngetval; 
    sem_t mutex, nempty, nstored; 
} sharedtype;




int main(int argc, char **argv)
{
    sharedtype * shared;
    key_t key;
    int shmid, semid;
    int i, j, prodcount[MAXNTHREADS], conscount[MAXNTHREADS];

    shared = mmap(NULL, sizeof(sharedtype),
                PROT_READ | PROT_WRITE, MAP_SHARED, -1, 0);

    /* Wrong argv */
    if (argc != 4)
    {
        printf("usage: newconsumer <#items> <#producers> <#consumers>\n");
        exit(1);
    }
    nitems = atoi(argv[1]);
    nproducers = min(atoi(argv[2]), MAXNTHREADS);
    nconsumers = min(atoi(argv[3]), MAXNTHREADS);
    pid_t chpidpr [nproducers];
    pid_t chpidcon [nconsumers];
    /* initilising semaphores */
    sem_init(&(shared->mutex), 0, 1);
    sem_init(&(shared->nempty), 0, NBUFF);
    sem_init(&(shared->nstored), 0, 0);


    for (i = 0; i < nproducers; i++) {
        prodcount[i] = 0;
        switch (chpidpr[i] = fork())
        {
            case -1: 
                printf("fork error"); 
                return 1;
            case 0: 
                for (;;) 
                {
                    sem_wait(&shared->nempty); 
                    sem_wait(&shared->mutex);
                    if (shared->nput >= nitems) 
                    {
                        sem_post(&(shared->nstored));
                        sem_post(&(shared->nempty));
                        sem_post(&(shared->mutex));
                        return 0; 
                    }
                    shared->buff[(shared->nput) %NBUFF] = shared->nputval;
                    (shared->nput)++;
                    (shared->nputval)++;
                    sem_post(&(shared->mutex));
                    sem_post(&(shared->nstored));
                    prodcount[i] += 1;
                }
        }
    }
    for (i = 0; i < nproducers; i++) 
    {
        printf("producer count[%d] = %d\n", i, prodcount[i]);
    }
    for (i = 0; i < nconsumers; i++) {
        conscount[i] = 0;
        switch (chpidcon[i] = fork())
        {
            case -1: 
                printf("error"); 
                return 1;
            case 0: 
                for (;;) 
                {
                    sem_wait(&(shared->nstored)); 
                    sem_wait(&(shared->mutex));
                    if (shared->nget >= nitems) 
                    {
                        sem_post(&(shared->nstored));
                        sem_post(&(shared->mutex));
                        return 0;
                    }
                    j = shared->nget % NBUFF;
                    if (shared->buff[j] != shared->ngetval)
                    {
                        printf("error: buff[%d] = %d\n", j, shared->buff[j]);
                    }
                    shared->nget++;
                    shared->ngetval++;
                    sem_post(&(shared->mutex));
                    sem_post(&(shared->nempty)); 
                    conscount[i] += 1;
                }
        }
    }


    for (i = 0; i < nconsumers; i++) 
    {
        printf("consumer count[%d] = %d\n", i, conscount[i]);
    }
    /* destroying semaphores */
    sem_destroy(&(shared->mutex));
    sem_destroy(&(shared->nempty));
    sem_destroy(&(shared->nstored));
    exit(0);
}
user3608127
  • 105
  • 1
  • 7
  • Are you sure your `mmap` call is correct? – rjp May 06 '14 at 18:14
  • @RJP added (sharedtype*) before mmap to be sure. Didn't help (of course). Maybe it is impossible to create shared memory usung -1 in fd field? So what can I use instead? – user3608127 May 06 '14 at 18:29
  • `fd` should be a file descriptor that you would obtain from `open()`. You've added a cast, but you should add a check against the error result from `mmap()`: `if (shared == (sharedtype *)-1) { // error }` – rjp May 06 '14 at 18:33

1 Answers1

0

It looks like your mmap call has failed and return -1. You aren't checking for this condition.

I did a quick addition, and it looks like mutex is at an offset of 56, or 0x38 from the base of sharedtype. Based on the crash report, sem = 0x37, which would be the address of shared->mutex if shared == -1.

I can't find any documentation on why one would call mmap with fd == -1, but I think this may be the source of the issue, combined with not validating the result.

rjp
  • 1,760
  • 13
  • 15
  • I made the same conclusion. Could you tell me what can I use instead to create shared memory? – user3608127 May 06 '14 at 18:33
  • http://stackoverflow.com/questions/21311080/linux-shared-memory-shmget-vs-mmap Try this. I don't usually do high level OS stuff, just embedded, so for me, all memory is shared. That question should point you in the right direction, though. – rjp May 06 '14 at 18:37
  • This resource is probably better. That question I linked doesn't actually cover implementing. This seems pretty comprehensive: http://menehune.opt.wfu.edu/Kokua/More_SGI/007-2478-008/sgi_html/ch03.html – rjp May 06 '14 at 18:41
  • Thanks a lot for your help! Hope I'll solve the problem. – user3608127 May 06 '14 at 19:05