I made this code that inserts a structure into shared memory. I made debug prints to try to figure out where the processes were stopping and why there was an error. Apparently by doing operations on the elements in shared memory it goes into error but I don't understand why. How can I solve it?
static shared_pid_data *shared_pid_atom;
static int shmidA;
static int semidA;
void atomSharedPidInit(){
key_t key = ftok("shmfileA",65);
printf("atomSharedPidInit - key = ftok\n");
shmidA = shmget(key, sizeof(shared_pid_data), 0666|IPC_CREAT);
printf("atomSharedPidInit - shmget\n");
shared_pid_atom = (shared_pid_data*) shmat(shmidA, (void*)0, 0);
printf("atomSharedPidInit - shmat\n");
key_t sem_key = ftok("semfileA", 75);
printf("atomSharedPidInit - sem_key = ftok\n");
semidA = semget(sem_key, 1, 0666 | IPC_CREAT);
printf("atomSharedPidInit - semget\n");
semctl(semidA, 0, SETVAL, 1);
printf("atomSharedPidInit - semctl\n");
}
void lockA() {
struct sembuf sba = {(unsigned short) 0, -1, 0};
semop(semidA, &sba, 1);
}
void unlockA() {
struct sembuf sba = {(unsigned short) 0, 1, 0};
semop(semidA, &sba, 1);
}
void atomSharedPidWrite(pid_t pid) {
lockA();
printf("atomSharedPidWrite - lock\n");
int dim = shared_pid_atom->dimensione;
printf("atomSharedPidWrite - int dim\n");
if (dim < 1000) {
printf("atomSharedPidWrite - if\n");
shared_pid_atom->atomi_pid[shared_pid_atom->dimensione] = pid;
shared_pid_atom->dimensione++;
printf("pid : %d dimensione : %d ",shared_pid_atom->atomi_pid[shared_pid_atom->dimensione-1],shared_pid_atom->dimensione);
} else {
fprintf(stderr, "Shared memory is full\n");
}
unlockA();
}
int main (){
atomSharedPidInit();
printf("simulazione - atomSharedPidInit\n");
alarm((unsigned int)sim_duration);
printf("simulazione - alarm\n");
print_statistics();
for (int i = 0; i < n_atomi_init; i++) {
atomoPID = fork();
if (atomoPID == 0) {
printf("Atomo - fork\n");
srand((unsigned int)(time(NULL) + getpid()));
printf("Atomo - srand\n");
atomSharedPidWrite(getpid());
printf("Atomo - atomSharedPidWrite(getpid())\n");
int numero_atomico = rand() % max_num_atomico + min_num_atomico;
printf("%d %d %d ", numero_atomico, max_num_atomico, min_num_atomico);
char num_atomico_str[10];
sprintf(num_atomico_str, "%d", numero_atomico);
execl("./atomo", "./atomo", num_atomico_str, NULL);
exit(0);
} else if (atomoPID < -1) {
kill(getpid(), SIGINT);
exit(EXIT_FAILURE);
}
}
}
this is what I get by starting the process:
atomSharedPidInit - key = ftok
atomSharedPidInit - shmget
atomSharedPidInit - shmat
atomSharedPidInit - sem_key = ftok
atomSharedPidInit - semget
atomSharedPidInit - semctl
simulazione - atomSharedPidInit
simulazione - alarm
Current state:
Total energy: 0
Total energy consumed: 0
Total energy available: 0
Total atomi attivi: 0
Total scissions: 0
Total activations: 0
Total scorie: 0
+---------------------------------------------------+
Atomo - fork
Atomo - srand
atomSharedPidWrite - lock
Atomo - fork
Atomo - srand
Atomo - fork
Atomo - srand
Atomo - fork
Atomo - fork
Atomo - srand
Atomo - srand
atomSharedPidWrite - lock
atomSharedPidWrite - lock
atomSharedPidWrite - lock
atomSharedPidWrite - lock
make: *** [Makefile:38: run] Errore di segmentazione (creato dump del core)
even if I do a very banal operation like shared_pid_atom->dimensione = 0;
on the shared memory, it doesn't get done. I don't understand why.
I suggest you to check if the returned values of shmidA
, semidA
and shared_pid_atom
are valid: maybe you do not have the permissions to access the shared memory.
It seems your children processes are dying before the
int dim = shared_pid_atom->dimensione;
is executed, so maybe the pointer shared_pid_atom
isn't valid.
Furthermore, your lock does not work:
I checked your code, and once the lock errors are corrected, and the files used for shared resources are existent, the program works OK and I see no need to call the shmget repeatedly, you can use the shared_pid_atom
pointer you already have.
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
typedef struct _shared_pid_data
{
uint32_t dimensione;
uint32_t atomi_pid[1000];
}shared_pid_data;
static shared_pid_data *shared_pid_atom;
static int shmidA;
static int semidA;
void print_errno_and_die(const char * s)
{
const int err = errno;
printf("%s error: %i, %s\n", s, err, strerror(err));
exit(0);
}
void atomSharedPidInit(){
printf("+%s\n", __func__);
struct stat statbuf;
if (stat("./shmfileA", &statbuf) == -1)
{
print_errno_and_die("stat");
}
key_t key = ftok("./shmfileA",65);
printf("\tkey: %i\n", key);
if (-1 == key)
{
print_errno_and_die("key ftok");
}
shmidA = shmget(key, sizeof(shared_pid_data), 0666|IPC_CREAT);
printf("\tshmidA: %i\n", shmidA);
if (-1 == shmidA)
{
print_errno_and_die("shmget");
}
shared_pid_atom = (shared_pid_data*) shmat(shmidA, (void*)0, 0);
printf("\tshared_pid_atom: %p\n", shared_pid_atom);
if ((void *)-1 == shared_pid_atom)
{
print_errno_and_die("shared_pid_atom");
}
if (stat("./semfileA", &statbuf) == -1)
{
print_errno_and_die("stat semfileA");
}
key_t sem_key = ftok("./semfileA", 75);
printf("\tsem_key: %i\n", sem_key);
if (-1 == sem_key)
{
print_errno_and_die("sem key");
}
semidA = semget(sem_key, 1, 0666 | IPC_CREAT);
printf("\tsemidA has value: %i\n", semidA);
if (-1 == semidA)
{
print_errno_and_die("semidA");
}
const int ret_semctl = semctl(semidA, 0, SETVAL, 0);
printf("\tsemctl returns: %i\n", ret_semctl);
if (ret_semctl < 0)
{
print_errno_and_die("semctl");
}
shared_pid_atom->dimensione = 0;
printf("-%s\n", __func__);
}
void lockA() {
struct sembuf sops[2];
sops[0].sem_num = 0;
sops[0].sem_op = 0; // wait for 0
sops[0].sem_flg = 0;
sops[1].sem_num = 0;
sops[1].sem_op = 1; // get the semaphore
sops[1].sem_flg = 0;
if (semop(semidA, sops, 2) == -1) {
perror(__func__);
exit(EXIT_FAILURE);
}
}
void unlockA() {
struct sembuf sops;
sops.sem_num = 0;
sops.sem_op = -1; // unlock the semaphore
sops.sem_flg = 0;
if (semop(semidA, &sops, 1) == -1) {
perror(__func__);
exit(EXIT_FAILURE);
}
}
void atomSharedPidWrite(pid_t pid) {
printf("\t+%s: pid %i\n", __func__, pid);
printf("\t\tpid %i +lockA\n", pid);
lockA();
printf("\t\tpid %i -lockA\n", pid);
int dim = shared_pid_atom->dimensione;
if (dim < 1000) {
shared_pid_atom->atomi_pid[shared_pid_atom->dimensione] = pid;
shared_pid_atom->dimensione++;
printf("\t\tpid: %u dimensione: %" PRIu32 "\n",shared_pid_atom->atomi_pid[shared_pid_atom->dimensione-1],shared_pid_atom->dimensione);
} else {
fprintf(stderr, "\tShared memory is full\n");
}
printf("\t\tpid %i +unlockA\n", pid);
unlockA();
printf("\t\tpid %i -unlockA\n", pid);
printf("\t-%s: pid %i\n", __func__, pid);
}
int main (){
atomSharedPidInit();
const int n_atomi_init = 5;
int atomoPID[n_atomi_init];
for (int i = 0; i < n_atomi_init; i++) {
atomoPID[i] = fork();
if (atomoPID[i] == 0) {
printf("\tchild %i forked OK with PID %i\n", i, getpid());
srand((unsigned int)(time(NULL) + getpid()));
atomSharedPidWrite(getpid());
const int max_num_atomico = 100;
const int min_num_atomico = 10;
int numero_atomico = rand() % max_num_atomico + min_num_atomico;
printf("\tnumeri: %d %d %d\n", numero_atomico, max_num_atomico, min_num_atomico);
const int wait_ms = rand() % 200;
printf("\tchild %i is going to die in %i ms\n", i, wait_ms);
usleep(wait_ms * 1000);
//char num_atomico_str[10];
//sprintf(num_atomico_str, "%d", numero_atomico);
//execl("./atomo", "./atomo", num_atomico_str, NULL);
exit(0);
} else if (atomoPID[i] < -1) {
printf("\tsomething really bad happened on child %i: atomoPID[i] = %i\n", i, atomoPID[i]);
kill(getpid(), SIGINT);
exit(EXIT_FAILURE);
}
}
printf("MAIN: waiting for the children completed OK\n");
for (int i = 0; i < n_atomi_init; i++)
{
int wstatus;
waitpid(atomoPID[i], &wstatus, 0);
printf("MAIN: child %i completed OK\n", i);
}
printf("MAIN: all the children completed OK\n");
printf("MAIN: dimension is %" PRIu32 "\n", shared_pid_atom->dimensione);
printf("MAIN: bye\n");
}
Outoput:
+atomSharedPidInit
key: 1093279968
shmidA: 98346
shared_pid_atom: 0x7f80684f4000
sem_key: 1261052132
semidA has value: 1
semctl returns: 0
-atomSharedPidInit
child 0 forked OK with PID 95059
+atomSharedPidWrite: pid 95059
pid 95059 +lockA
pid 95059 -lockA
pid: 95059 dimensione: 1
pid 95059 +unlockA
pid 95059 -unlockA
-atomSharedPidWrite: pid 95059
child 1 forked OK with PID 95060
numeri: 13 100 10
child 0 is going to die in 136 ms
+atomSharedPidWrite: pid 95060
pid 95060 +lockA
pid 95060 -lockA
pid: 95060 dimensione: 2
pid 95060 +unlockA
pid 95060 -unlockA
-atomSharedPidWrite: pid 95060
numeri: 76 100 10
child 1 is going to die in 156 ms
child 2 forked OK with PID 95061
+atomSharedPidWrite: pid 95061
pid 95061 +lockA
pid 95061 -lockA
pid: 95061 dimensione: 3
pid 95061 +unlockA
pid 95061 -unlockA
-atomSharedPidWrite: pid 95061
numeri: 21 100 10
child 2 is going to die in 102 ms
MAIN: waiting for the children completed OK
child 3 forked OK with PID 95062
+atomSharedPidWrite: pid 95062
pid 95062 +lockA
pid 95062 -lockA
pid: 95062 dimensione: 4
pid 95062 +unlockA
pid 95062 -unlockA
-atomSharedPidWrite: pid 95062
numeri: 24 100 10
child 4 forked OK with PID 95063
child 3 is going to die in 137 ms
+atomSharedPidWrite: pid 95063
pid 95063 +lockA
pid 95063 -lockA
pid: 95063 dimensione: 5
pid 95063 +unlockA
pid 95063 -unlockA
-atomSharedPidWrite: pid 95063
numeri: 55 100 10
child 4 is going to die in 195 ms
MAIN: child 0 completed OK
MAIN: child 1 completed OK
MAIN: child 2 completed OK
MAIN: child 3 completed OK
MAIN: child 4 completed OK
MAIN: all the children completed OK
MAIN: dimension is 5
MAIN: bye