ftruncate() invalid arguement error - c

I just started learned about shared memory and we are suppose to create an object of shared memory for my assignment, but I keep getting an error when I run my program.
The error comes from the ftruncate() function and it keeps telling me its an invalid argument, here's my code segment for the shared memory:
struct container* rPtr;
int fd;
/* Creates shared memory object and sets it size */
fd = shm_open("/collatzRegion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd == -1)
{ perror("shm_open");
return 1;
}
if ((ftruncate(fd, sizeof(struct container))) == -1)
{ perror("ftruncate");
return 1;
}
/* Maps shared memory object */
rPtr = mmap(NULL, sizeof(struct container), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if ( rPtr == MAP_FAILED)
{ perror("mmap");
return 1;
}
and my structure, that is defined before my main(), is:
/* Defines "structure" of shared memory */
#define MAX_LEN 10000
struct container
{ int length;
int buf[MAX_LEN];
};

Related

Why is my string not showing after transfer via SHM?

I've created the following types to transfer a list of nodes from one process to the other one:
typedef struct {
char *from;
char *to;
} Edge;
typedef struct {
size_t numEdges;
Edge *fst;
} EdgeList;
typedef struct {
EdgeList buffer[BUFFER_SIZE];
...
} CircularBuffer; /**< used as shared memory. */
This is what the process that sends the EdgeList looks like:
// open shared memory -> shm_open()
int shm_fd = shm_open(SHM_PATH, O_RDWR, S_IRUSR | S_IWUSR);
...
// map shared memory into memory -> mmap()
CircularBuffer *shm = mmap(NULL, sizeof(CircularBuffer),
PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
...
while (true) {
shm->buffer[...] = getSolution(...);
...
}
...
This is what the process that receives the EdgeList looks like:
// create shared memory -> shm_open()
int shm_fd = shm_open(SHM_PATH, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
...
// set shared memory size -> ftruncate()
ftruncate(shm_fd, sizeof(CircularBuffer);
...
// map shared memory into memory -> mmap()
CircularBuffer *shm = mmap(NULL, sizeof(CircularBuffer),
PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
...
EdgeList bestSolution = {.numEdges = SIZE_MAX, .fst = NULL};
while (true) {
EdgeList solution = shm->buffer[...];
if (solution.numEdges < bestSolution.numEdges) {
bestSolution = solution;
// I can read 'bestSolution.numEdges' here just fine.
// But i can't read 'bestSolution.fst[i].from' and 'bestSolution.fst[i].to' for some reason.
}
...
}
...
Now here is where things behave unexpectedly: The receiving process is not showing me any strings from the shared memory but everything else works just as expected.
I have access to bestSolution.numEdges after it being read from the shared memory, but not to bestSolution.fst[i].from and bestSolution.fst[i].to (with i being a legal index from that array).
When I try to read these strings, I only see (null) instead of the strings. Can I fix this issue?

How to detect which piece of my code is generating "Fatal error: glibc detected an invalid stdio handle" error?

I'm trying to code a simple program to copy a file into another using 2 processes.
I want to use shared memory to open both files and get a piece of shared memory of 1Byte to be used as exchange memory in a mutually exclusive way.
So the main process should open both files and put them in shared memories;
fork twice, I obtain 2 processes A and B.
Process A should read 1 byte of the first file, put it in the shared exchange memory and unlock the mutex for process B.
Process B should copy the file from the shared exchange memory and put it in its file and unlock the mutex for process A.
And so on.
#define SIZE 4096
void reader_process(FILE* fptr,char*exch, sem_t*mut){
while(1){
sem_wait(mut);
*exch = (char) getc(fptr);
sem_post(mut+1);
}
}
void writer_process(FILE* fptr,char*exch, sem_t*mut){
if(*exch == EOF){
printf("done\n");
exit(0);
}
while(1){
sem_wait(mut);
putc((int)*exch,fptr);
sem_post(mut-1);
}
}
int main(int argc, char *argv[]){
FILE* shared_f_ptr[2];
pid_t pid;
//2 files name.
char *files[2];
int fd[2];
//open files.
files[0] = argv[1];
printf("%s\n",files[0]);
FILE* fpointer1 = fopen(files[0],"r+");
if (fpointer1 == NULL){
perror("fopen\n");
exit(-1);
}
fd[0] = fileno(fpointer1);
files[1] = argv[2];
printf("%s\n",files[1]);
FILE* fpointer2 = fopen(files[1],"r+");
if (fpointer2 == NULL){
perror("fopen\n");
exit(-1);
}
fd[1] = fileno(fpointer2);
//shared File pointers.
shared_f_ptr[0] = (FILE*)mmap(NULL, SIZE*sizeof(char),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
fd[0], 0);
if (shared_f_ptr[0] == MAP_FAILED){
perror("mmap\n");
exit(-1);
}
shared_f_ptr[1] = (FILE*)mmap(NULL, SIZE*sizeof(char),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
fd[1], 0);
if (shared_f_ptr[1] == MAP_FAILED){
perror("mmap\n");
exit(-1);
}
//shared mem for 1B exchange.
char *shared_exchange = (char*)mmap(NULL, sizeof(char),
PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS,
-1, 0);
if (shared_exchange == MAP_FAILED){
perror("mmap\n");
exit(-1);
}
//mutex.
sem_t *mut = (sem_t*)mmap(NULL, 2*sizeof(sem_t),
PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS,
-1, 0);
sem_init(&mut[0],1,0);
sem_init(&mut[1],1,0);
//fork.
pid = fork();
if (pid == 0) {
reader_process(shared_f_ptr[0],
shared_exchange, &mut[0]);
}
if (pid == -1){
perror("fork\n");
exit(-1);
}
else pid = fork();
if (pid == 0) writer_process(shared_f_ptr[1],
shared_exchange, &mut[1]);
if (pid == -1){
perror("fork\n");
exit(-1);
}
else{
sem_post(&mut[0]);
}
}
I don't expect the error i am getting Fatal error: glibc detected an invalid stdio handle but i don't really know how to find what's causing the problem.
Don't do this:
//shared File pointers.
shared_f_ptr[0] = (FILE*)mmap(NULL, SIZE*sizeof(char),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
fd[0], 0);
if (shared_f_ptr[0] == MAP_FAILED){
perror("mmap\n");
exit(-1);
}
shared_f_ptr[1] = (FILE*)mmap(NULL, SIZE*sizeof(char),
PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
fd[1], 0);
if (shared_f_ptr[1] == MAP_FAILED){
perror("mmap\n");
exit(-1);
}
Use this instead:
shared_f_ptr[0] = fpointer1;
shared_f_ptr[1] = fpointer2;
Don't use the file descriptors underlying each FILE. Instead, simply use the FILE itself.
Also, instead of using fpointer1 and fpointer2, just use shared_f_ptr[0] and shared_f_ptr[1].
This is a possible definition of the FILE structure:
typedef struct _IO_FILE
{
int __fd;
int __flags;
int __unget;
char *__buffer;
struct {
size_t __orig;
size_t __size;
size_t __written;
} __bufsiz;
fpos_t __fpos;
} FILE;
As you can see, it's a structure, not just a flat pointer.

shm_open() leads to a No such file or directory

Description :
I have a project directory named "Projet" which contain two directory named "Serveur" and "Client".
(1) Serveur contains serveur.c (2) Client contains client.c
Referenting to the man, I choose as a name : "/shm_request_stack".
Source files description :
serveur.c :
#define SHM_REQUEST "/shm_request_stack"
int main(void) {
sem_t shm = open_shm(SHM_REQUEST,
O_RDWR | O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR);
unlink_shm(SHM_REQUEST);
size_t memsize = sizeof(int);
setsize_shm(shm, memsize);
int * ptr = project_shm(shm, memsize);
*ptr = 0;
while(*ptr == 0);
printf("Client modify the value\n");
}
client.c :
#define SHM_REQUEST "/shm_request_stack"
int main(void) {
sem_t shm = open_shm(SHM_REQUEST,
O_RDWR,
S_IRUSR | S_IWUSR);
unlink_shm(SHM_REQUEST);
size_t memsize = sizeof(int);
int * ptr = project_shm(shm, memsize);
*ptr = 1;
}
Envelope functions
int open_shm(char *name, int oflag, mode_t mode) {
int shm = shm_open(name, oflag, mode);
if (shm == -1) {
fprintf(stderr, "Error while opening %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
return shm;
}
void unlink_shm(char *name) {
if (shm_unlink(name) == -1) {
perror("sem_unlink");
exit(EXIT_FAILURE);
}
}
void setsize_shm(int shm, size_t size) {
if (ftruncate(shm, size) == -1) {
perror("ftruncate");
exit(EXIT_FAILURE);
}
}
void * project_shm(int shm, size_t size) {
int *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
if (ptr == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
return ptr;
}
Problems :
The client can't find the named shm create by the server.
I tried to found the shared memory with ipcs -m but I've not.
I try to modify the value from the server and it's works so the memory exist.
How can I successfully open the shm from the client ?
You appear to be deleting the shared object immediately after creating it (unlink).
It is a bit like a file. If you have an open reference to the object then it is retained, but the unlink removes the name. That is why the server can still write to the object after the unlink (she is still in scope), but the client cannot open the object by name.
The critical words in the doc you quote are : "all open and map references" - what you can't do is create a new reference after the unlink.

c - writing to shared memory segment causes segmentation fault

I'm having problems with writing to shared memory segment. Here's the code:
EDIT: after I removed that == (mistake), now I'm getting Bus Error (Core Dumped), here's the edited code:
// Struct for data from shared memory
typedef struct {
pthread_mutex_t shared_mutex;
int last_used_job_id;
} shared1;
static void *job_generator(void *param)
{
int J = *((int *) param);
shared1 *shd;
int shm;
int job_id;
// Open shared memory, don't create it if doesn't exist
shm = shm_open("/lab5", O_RDWR, 00600);
// Check
if (shm == -1) {
// Open shared memory, create it if doesn't exist (O_CREAT)
shm = shm_open(q_name, O_RDWR | O_CREAT, 00600);
// Map space for struct
shd = mmap(NULL, sizeof(shared1), PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
if (shd == (void *) -1) {
perror ( "mmap" );
exit(1);
}
// Initialize mutex
if (pthread_mutex_init(&(shd->shared_mutex), NULL) != 0)
{
printf("Mutex initialization failed!\n");
exit(1);
}
}
else
{
// Map space for struct
shd = mmap(NULL, sizeof(shared1), PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
if (shd == (void *) -1) {
perror ( "mmap" );
exit(1);
}
}
// Lock mutex
pthread_mutex_lock(&(shd->shared_mutex));
job_id = shd->last_used_job_id + 1;
shd->last_used_job_id = job_id + J;
printf("a: %d\n", shd->last_used_job_id);
return NULL;
}
it's caused by any of the instructions which are using shd, so any of these:
// Lock mutex
pthread_mutex_lock(&(shd->shared_mutex));
job_id = shd->last_used_job_id + 1;
shd->last_used_job_id = job_id + J;
printf("a: %d\n", shd->last_used_job_id);
I think this is where your problem lies:
shd == mmap(NULL, sizeof(shared1), PROT_READ | PROT_WRITE, MAP_SHARED, shm, 0);
You're comparing shd to the return value of mmap with '=='. I think you meant to use a single '=' which would assign the return value to shd.

Shared Memory Ftruncate

I am trying to share some data between parent and child process. For the first time I can write and read data to shared memory. However if I want to write one more data, I got truncate error. I know something is wrong with my code. I feel like I need to implement base address part but I don't know how to do it.
void *attach_shmem(int shmem_fd, int object_size){
void *addr;
/* resize it to something reasonable */
if (ftruncate(shmem_fd, object_size) == -1){
perror("failed to resize shared memory object\n");
exit(EXIT_FAILURE);
}
addr = mmap(base, object_size, PROT_READ | PROT_WRITE, MAP_SHARED, shmem_fd, 0);
if (addr == MAP_FAILED){
perror("failed to map shared memory object\n");
exit(EXIT_FAILURE);
}
return addr;
}
void *map_shmem(char *path, int object_size){
int shmem_fd;
/* open one that has already been created */
shmem_fd = shm_open(path, O_RDWR, S_IRUSR | S_IWUSR);
if (shmem_fd == -1){
fprintf(stdout, "failed to open shared memory object\n");
exit(EXIT_FAILURE);
}
return attach_shmem(shmem_fd, object_size);
}
void add_ip_to_shared_memory(char *ip, int val, int num)
{
sem_t *sem = sem_open("/basag_sem", 0);
struct SharedMem *node;
char ip_binary[100];
void *addr;
strcpy(ip_binary, transform_ip_to_bits(ip));
node = malloc(sizeof(struct SharedMem));
strcpy(node->ip, strndup(ip_binary, num));
node->val = val;
//semaphore block
sem_wait(sem);
//add node to shared memory
addr = map_shmem("gungor_shmem", sizeof(*node));
memcpy(addr, node, sizeof(*node));
base = addr;
sem_post(sem);
free(node);
//semaphore release
//write_to_screen(node->ip);
setbuf(stdout, NULL);
}

Resources