Ad

Shm_open Segmentation Fault And Permission Failed

- 1 answer

I am new to Linux and i am trying to create a shared memory object which stores the collatz conjecture calculated in child process and prints it in parent process. I have already read the man pages for the commands. When I create the object it prints permission denied and segmentation fault(core dumped). Only one time it somehow passed that step then I got the mapping failed error.I am using ubuntu 18.04 on a virtual machine

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<sys/wait.h>
#include<sys/stat.h>

int main(int argc,char** argv)
{
pid_t pid;
pid = fork();
int page_size = 4096;
char obj[] = "name";
int num = atoi(argv[1]);
    if(num < 1)
{
    printf("Please input a greater number\n");
    return 0;
}

if(pid < 0)
{
    fprintf(stdout,"Fork failed\n");
}
else if(pid == 0)
{
    int fd1 = 0;
    void *ptr1 = NULL;
    fd1 = shm_open(obj,O_CREAT|O_TRUNC,S_IRWXU);
    if (fd1 == -1)
    {
        perror("error:");
        exit(0);
    }
    ftruncate(fd1,page_size);
    ptr1 = mmap(0,page_size,PROT_WRITE,MAP_SHARED,fd1,0);
    if(ptr1 == MAP_FAILED)
    {
        fprintf(stdout,"Mapping failed");
        exit(0);
    }
    else
    {
        while(num != 1)
        {
            if(num%2 == 0)
                num = num / 2;
            else
                num = (num * 3) + 1;

            sprintf(ptr1,"%d, ",num);
        }
    }
}
else
{
    wait(NULL);
    int fd = 0;
    void *ptr = NULL;
    shm_open(obj,O_RDONLY,S_IRWXU);
    ptr = mmap(0,page_size,PROT_READ,MAP_SHARED,fd,0);
    char *pr = (char *)ptr;
    fprintf(stdout,pr);
    shm_unlink(obj);

}
return 0;
}
Ad

Answer

Your code needs a couple of changes, some for better programming practices and some for fixing the actual functionality:

#include <all.h>

int main(int argc, char **argv) {
    pid_t pid;
    pid = fork();
    int page_size = 4096;
    char obj[] = "name";
    // check argc otherwise you'll segfault
    if (argc < 2) {
        printf("Please provide a second argument.\n");
        // if the program errors it should not return 0
        return 1;
    }
    int num = atoi(argv[1]);
    if (num < 1) {
        printf("Please input a greater number\n");
        return 1;
    }

    if (pid < 0) {
        // no need for fprintf(stdout
        printf("Fork failed\n");
    } else if (pid == 0) {
        int fd1 = 0;
        char *ptr1 = NULL;
        // we need to open with O_RDWR otherwise mmap will fail
        fd1 = shm_open(obj, O_CREAT | O_TRUNC | O_RDWR, 0666);
        if (fd1 == -1) {
            perror("shm_open error");
            return 1;
        }
        ftruncate(fd1, page_size);
        // cast it to char* directly, no need for void pointer stuff
        ptr1 = (char *) mmap(0, page_size, PROT_WRITE, MAP_SHARED, fd1, 0);
        if (ptr1 == MAP_FAILED) {
            // perror for debugging
            perror("mmap error");
            printf("Mapping failed.\n");
            return 1;
        } else {
            while (num != 1) {
                if (num % 2 == 0)
                    num = num / 2;
                else
                    num = (num * 3) + 1;

                // we need to shift the pointer so it stops truncating
                ptr1 += sprintf(ptr1, "%d, ", num);
            }
        }
    } else {
        wait(NULL);
        // move these to one like and cast to char* directly
        int fd = shm_open(obj, O_RDONLY, S_IRWXU);
        char *ptr = (char*) mmap(0, page_size, PROT_READ, MAP_SHARED, fd, 0);
        // no need for fprintf(stdout, and also use %s\n as a format to add a newline
        printf("%s\n", ptr);
        shm_unlink(obj);
    }
    return 0;
}
Ad
source: stackoverflow.com
Ad