C - IPC semaphores with fork - unix

I'm having a problem with following program:
What it was supposed to do:
First child process should get a number from STDIN and set it to shared variable.
Second child process should read number from shared variable and print it binary on STDOUT.
What it does:
It never asks for a number, after running it, it just prints inifnite number of zero's. It looks like it jumps straight away into a second child and never leaves it.
Code:
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* jest zdefiniowane w sys/sem.h */
#else
union semun
{
int val;
struct semid_ds* buf;
unsigned short int* array;
struct seminfo* __buf;
};
#endif
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <fcntl.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/mman.h>
//shared
static int *glob_var;
struct sembuf operacja;
void operacjaSem(int, int, int);
int main(void)
{
/*---------------------------------------*/
//shared memory
glob_var = mmap(NULL, sizeof(*glob_var), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
/*---------------------------------------*/
//semafory
key_t klucz;
int semafor;
union semun ustaw;
//tworze jednoznaczny klucz dla semaforow
if((klucz = ftok(".", 'B')) == -1)
{
fprintf(stderr, "blad tworzenia klucza\\n");
exit(1);
}
//stworzenie semaforow
if((semafor = semget(klucz, 2, IPC_CREAT | IPC_EXCL | 0600)) == -1)
{
fprintf(stderr, "blad tworzenia semaforow\\n");
exit(1);
}
//inicjacja semaforow
ustaw.val = 1;
if(semctl(semafor, 0, SETVAL, ustaw) == -1)
{
fprintf(stderr, "blad ustawienia semafora0\\n");
exit(1);
}
ustaw.val = 0;
if(semctl(semafor, 1, SETVAL, ustaw) == -1)
{
fprintf(stderr, "blad ustawienia semafora1\\n");
exit(1);
}
if(fork() == 0)
{
//first child process
while(1)
{
if(semctl(semafor, 0, GETVAL) == 1)
{
//ustawiam zmienna wspoldzielona
char buf2[128];
fgets(buf2, 128, 0);
*glob_var = atoi(buf2);
//printf("buf: %d", *glob_var);
//przestawiam semafory
operacjaSem(semafor, 0, -1);
operacjaSem(semafor, 1, 1);
}
}
}
if(fork() == 0)
{
//second child process
while(1)
{
if(semctl(semafor, 1, GETVAL) == 1)
{
operacjaSem(semafor, 1, -1);
//odczytuje i wypisuje
int x = *glob_var;
int p[32];
for(int z = 0; z < 32; z++)
{
if(x % 2 == 1 || x % 2 == -1) p[z] = 1;
else p[z] = 0;
x = x >> 1;
}
for(int z = 31; z >= 0; z--)
printf("%d", p[z]);
printf("\n");
//przestawiam semafory
operacjaSem(semafor, 1, -1);
operacjaSem(semafor, 0, 1);
}
}
}
return 0;
}
void operacjaSem(int semafor, int nr, int op)
{
operacja.sem_num = nr;
operacja.sem_op = op;
operacja.sem_flg = 0;
if(semop(semafor, &operacja, 1) == -1)
{
fprintf(stderr, "blad operacji na semaforze\\n");
exit(1);
}
}

Change the first line that reads:
if(fork() == 0)
To something like
pid_t processID = fork();
if(processID == 0)
Change the second line that reads
if(fork() == 0)
To an else. More explicitly, for that second line, change:
}
if(fork() == 0)
{
//second child process
To:
}
else
{
if (processID < 0) {
printf ("Fork error\n"); exit(-1);
}
//second child process
And probably if the rest of your code is OK, it will start working. At least this will get your forks in good shape so you can keep working with the rest of the code.

Related

Stuck at solving leetcode Q5 using C [=34==ERROR: AddressSanitizer]

Please excuse for my massy code. This was best I could do.
I have been solving leetcode Q5 for a while; however, I couldn't solve it. This is the closest answer I have got.
I think it's acting correctly in terms of showing outputs. But has a runtime error when
let s = "tscvrnsnnwjzkynzxwcltutcvvhdivtmcvwdiwnbmdyfdvdiseyxyiiurpnhuuufarbwalzysetxbaziuuywugfzzmhoessycogxgujmgvnncwacziyybryxjagesgcmqdryfbofwxhikuauulaqyiztkpgmelnoudvlobdsgharsdkzzuxouezcycsafvpmrzanrixubvojyeuhbcpkuuhkxdvldhdtpkdhpiejshrqpgsoslbkfyraqbmrwiykggdlkgvbvrficmiignctsxeqslhzonlfekxexpvnblrfatvetwasewpglimeqemdgdgmemvdsrzpgacpnrbmomngjpiklqgbbalzxiikacwwzbzapqmatqmexxqhssggsyzpnvvpmzngtljlrhrjbnxgpcjuokgxcbzxqhmitcxlzfehwfiwcmwfliedljghrvrahlcoiescsbupitckjfkrfhhfvdlweeeverrwfkujjdwtcwbbbbwctwdjjukfwrreveeewldvfhhfrkfjkctipubscseioclharvrhgjldeilfwmcwifwhefzlxctimhqxzbcxgkoujcpgxnbjrhrljltgnzmpvvnpzysggsshqxxemqtamqpazbzwwcakiixzlabbgqlkipjgnmombrnpcagpzrsdvmemgdgdmeqemilgpwesawtevtafrlbnvpxexkeflnozhlsqexstcngiimcifrvbvgkldggkyiwrmbqaryfkblsosgpqrhsjeiphdkptdhdlvdxkhuukpcbhueyjovbuxirnazrmpvfascyczeuoxuzzkdsrahgsdbolvduonlemgpktziyqaluuaukihxwfobfyrdqmcgsegajxyrbyyizcawcnnvgmjugxgocysseohmzzfguwyuuizabxtesyzlawbrafuuuhnpruiiyxyesidvdfydmbnwidwvcmtvidhvvctutlcwxznykzjwnnsnrvcst"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int is_palindrome(char * s);
void get_substring(const char *str, char *substr, int start, int end);
char * longestPalindrome(char * s){
int strlength = strlen(s);
int end = strlength - 1;
int start = 0;
char substr[1000];
char *longstr = (char *)malloc(1000 * sizeof(char));
strcpy(longstr, "");
while (start <= end)
{
get_substring(s, substr, start, end);
// printf("%s\n", substr);
if (is_palindrome(substr) > strlen(longstr))
{
// printf("UPDATE : %s\n", substr);
strcpy(longstr, substr);
}
if (end == start)
{
start++;
end = strlength - 1;
}
else
{
end--;
}
}
// printf("LONG : %s", longstr);
return longstr;
}
void get_substring(const char *str, char *substr, int start, int end) {
int length = end - start + 1;
strncpy(substr, str + start, length);
substr[length] = '\0';
}
int is_palindrome(char * s){
int length = strlen(s);
int mid = length/2;
if (length % 2 == 0)
{
// printf("EVEN : %d\n", mid);
mid--;
int upperptr = mid+1;
int i = 0;
if (s[mid] != s[upperptr])
{
// printf("Returning FALSE [0]\n");
return 0;
}
while (mid-i >= 0 && upperptr+i <= length)
{
// printf("%c and %c and mid is %c\n", s[mid-i], s[upperptr+i], s[mid]);
if (s[mid-i] != s[upperptr+i])
{
// printf("Returning FALSE [1]\n");
return 0;
}
i++;
}
}
else
{
// printf("ODD: %d\n", mid+1);
int i = 0;
while (mid-i >= 0 && mid+i <= length)
{
// printf("%c and %c and mid is %c\n", s[mid-i], s[mid+i], s[mid]);
if (s[mid-i] != s[mid+i])
{
// printf("Returning FALSE [2]\n");
return 0;
}
i++;
}
}
// printf("Returning TRUE\n");
return length;
}
I had difficulties returning a local string. then found out that local string value can't be returned and has to be dynamically malloced and the pointer has to be returned.
So I fixed it (somehow, if it is right). But I reckon this is causing different - even harder - problems that I can't manage.

Error in MPI program when using MPI_Reduce function of MPI_MAXLOC

I want to use MPI_Reduce function find largest value and its PID(rank) at the same time, but the result shows it is not true, I don't know how to fix it, result:
PID:1, loc_num:2
PID:2, loc_num:3
PID:3, loc_num:4
global data: 1
coresponding PID: 0
my program:
#include <stdio.h>
#include <string.h>
#include <mpi.h>
int main(int argc, char *argv[])
{
//init MPI
int PID, P;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &P);
MPI_Comm_rank(MPI_COMM_WORLD, &PID);
struct{
int value;
int PID;
} in, out;
int value = 1;
in.value = value;
in.PID = PID;
for(int i = 1; i <= P; i++){
if (PID == i){
value = value + i;
printf("PID:%d, loc_num:%d \n",PID, value);
}
}
MPI_Reduce(&in, &out, 1, MPI_2INT, MPI_MAXLOC, 0, MPI_COMM_WORLD);
int max_PID = out.PID;
int max_num = out.value;
if (PID == 0){
printf("global data: %d \n", max_num);
printf("coresponding PID: %d \n",max_PID);
}
MPI_Finalize();
return 0;
}
I just follow the structure of in.value= value and in.PID=PID and then,every PID calculate value=value+PID so the answer is when PID=1, loc=2;when PID=2, loc=3 ...next compare all of them by max, and sent them to PID=0
There is no error in the MPI_Reduce of your example. As #Gilles pointed out, the issue is you are not assigning the newly calculated value to in.value.
If you put the assignment statement after calculation as below, then everything work as expected.
for(int i = 1; i <= P; i++){
if (PID == i){
value = value + i;
printf("PID:%d, loc_num:%d \n",PID, value);
}
}
in.value = value;
in.PID = PID;
MPI_Reduce(&in, &out, 1, MPI_2INT, MPI_MAXLOC, 0, MPI_COMM_WORLD);
In your example below, you are not assigning the calculated values to the in struct object.
in.value = value; // value is set as 1
in.PID = PID;
for(int i = 1; i <= P; i++){
if (PID == i){
value = value + i; // calculating the value but not assigning to in.value
printf("PID:%d, loc_num:%d \n",PID, value);
}
}
// uses the old value for in.value (i.e 1) for reduction
MPI_Reduce(&in, &out, 1, MPI_2INT, MPI_MAXLOC, 0, MPI_COMM_WORLD);

Incremental index doesn't change at end of for loop

I want to interface Arduino with PLC to pull some information.
My problem is at Function 3: Set alarm flag / reset flag. This function is used to compare history value and present value. I tried to process some integer number (test_number) and process like binary 16 bits data for finding 1 at some bit. I found the for loop in Findbit function, which should repeat 16 times, runs infinitely. It does not change the incremental index (variable name bit_1) which is still stuck at 1.
This is my code :
int test_number_array[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int test_number = 0;
int bit_1 = 0;
int Andbit = 0;
const char* message;
int flagAlarm[2][16] = {};
int flagReset[2][16] = {};
void setup()
{
// put your setup code here, to run once:
Serial.begin( 9600 );
}
void loop()
{
// put your main code here, to run repeatedly:
for (int j = 1; j <= 2; j++)
{
for (int i = 1; i <= 2; i++) // Example with 2 modbus address
{
unsigned int address = 40000 + i;
Serial.print ("Modbus address = ");
Serial.println(address, DEC);
pull_data(i);
Serial.print("Test number is ");
Serial.println(test_number);
Findbit(i);
Serial.println("------------------------------------------------- ");
}
}
while (1)
{
}
}
// ---------------Function 1 : Function finding alarm bit-----------------//
void Findbit(int i)
{
for (bit_1 = 0; bit_1 <= 15; bit_1++)
{
Andbit = test_number & 1;
Serial.print("Test number (BINARY) is ");
Serial.println(test_number, BIN);
Serial.print("Check at bit number ");
Serial.println(bit_1);
Serial.print("And bit is ");
Serial.println(Andbit, BIN);
Serial.print("flagAlarm(Before1) = ");
Serial.println(flagAlarm[i][bit_1]);
Serial.print("flagreset(Before1) = ");
Serial.println(flagReset[i][bit_1]);
if (Andbit == 1) //found "1" pass into loop
{
flagAlarm[i][bit_1] = 1;
}
else
{
}
Serial.print("flagAlarm(Before2) = ");
Serial.println(flagAlarm[i][bit_1]);
Serial.print("flagreset(Before2) = ");
Serial.println(flagReset[i][bit_1]);
Set_reset_flag(i,bit_1);
test_number = test_number >> 1;
Serial.print("flagAlarm(After) = ");
Serial.println(flagAlarm[i][bit_1]);
Serial.print("flagreset(After) = ");
Serial.println(flagReset[i][bit_1]);
Serial.println(" ");
}
}
// -----------------------Function 2 : Pull data------------------------- //
int pull_data(int i)
{
i = i - 1;
test_number = test_number_array[i];
return test_number;
}
// -------------Function 3 : Set alarm flag / reset flag ---------------- //
void Set_reset_flag(int i, int bit_1)
{
Serial.print("i = ");
Serial.println(i);
Serial.print("bit_1 = ");
Serial.println(bit_1);
if (flagAlarm[i][bit_1] == 1 && flagReset[i][bit_1] == 0)
{
Serial.print("Alarm at bit ");
Serial.println(bit_1);
flagAlarm[i][bit_1] = 0;
flagReset[i][bit_1] = 1;
}
else if (flagAlarm[i][bit_1] == 0 && flagReset[i][bit_1] == 1)
{
Serial.print("Reset Alarm at bit ");
Serial.println(bit_1);
flagReset[i][bit_1] = 0;
}
else if (flagAlarm[i][bit_1] == 1 && flagReset[i][bit_1] == 1)
{
Serial.print("Alarm still active at bit ");
Serial.println(bit_1);
flagAlarm[i][bit_1] = 0;
flagReset[i][bit_1] = 1;
}
else
{
}
}
Could it be that your bit_1 variable is modified from some other code not mentioned here, or get optimized at all? Also, is it necessary to make a loop counter a global variable? Can you declare it inside the Findbit function?

Removing MPI_Bcast()

So I have a some code where I am using MPI_Bcast to send information from the root node to all nodes, but instead I want to get my P0 to send chunks of the array to individual processes.
How do I do this with MPI_Send and MPI_Receive?
I've never used them before and I don't know if I need to loop my MPI_Receive to effectively send everything or what.
I've put giant caps lock comments in the code where I need to replace my MPI_Bcast(), sorry in advance for the waterfall of code.
Code:
#include "mpi.h"
#include <stdio.h>
#include <math.h>
#define MAXSIZE 10000000
int add(int *A, int low, int high)
{
int res = 0, i;
for(i=low; i<=high; i++)
res += A[i];
return(res);
}
int main(argc,argv)
int argc;
char *argv[];
{
int myid, numprocs, x;
int data[MAXSIZE];
int i, low, high, myres, res;
double elapsed_time;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
if (myid == 0)
{
for(i=0; i<MAXSIZE; i++)
data[i]=1;
}
/* star the timer */
elapsed_time = -MPI_Wtime();
//THIS IS WHERE I GET CONFUSED ABOUT MPI_SEND AND MPI_RECIEVE!!!
MPI_Bcast(data, MAXSIZE, MPI_INT, 0, MPI_COMM_WORLD);
x = MAXSIZE/numprocs;
low = myid * x;
high = low + x - 1;
if (myid == numprocs - 1)
high = MAXSIZE-1;
myres = add(data, low, high);
printf("I got %d from %d\n", myres, myid);
MPI_Reduce(&myres, &res, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
/* stop the timer*/
elapsed_time += MPI_Wtime();
if (myid == 0)
printf("The sum is %d, time taken = %f.\n", res,elapsed_time);
MPI_Barrier(MPI_COMM_WORLD);
printf("The sum is %d at process %d.\n", res,myid);
MPI_Finalize();
return 0;
}
You need MPI_Scatter. A good intro is here: http://mpitutorial.com/tutorials/mpi-scatter-gather-and-allgather/
I think in your code it could look like this:
elements_per_proc = MAXSIZE/numprocs;
// Create a buffer that will hold a chunk of the global array
int *data_chunk = malloc(sizeof(int) * elements_per_proc);
MPI_Scatter(data, elements_per_proc, MPI_INT, data_chunk,
elements_per_proc, MPI_INT, 0, MPI_COMM_WORLD);
If you really want use MPI_Send and MPI_Recv, then you can use something like this:
int x = MAXSIZE / numprocs;
int *procData = new int[x];
if (rank == 0) {
for (int i = 1; i < num; i++) {
MPI_Send(data + i*x, x, MPI_INT, i, 0, MPI_COMM_WORLD);
}
} else {
MPI_Recv(procData, x, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
}

mpi dot product using point to point operations fails when data is large

I have below code two get a dot product of two vectors of size VECTORSIZE. Code works fine until VECTORSIZE up to 10000 but then it gives unrelated results. When I tried to debug the program I have seen that processor 0 (root) finishes its job before all processors send their local results. I got the same situation when I utilized the MPI_Reduce() (code part 2). However if I use MPI_Scatter() before MPI_Reduce() it is OK.
#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
#define VECTORSIZE 10000000
#define ROOT 0
//[[## operation ConstructVectorPart()
void ConstructVector(double * vector, int size, short vectorEnu)
{
int i = 0;
if(vectorEnu == 1) // i.e vector 1
{
for(i = 0; i < size; i++)
{
vector[i] = 0.1 + (i%20)*0.1;
}
}
else if(vectorEnu == 2) // i.e. vector 2
{
for(i = 0 ; i < size; i++)
{
vector[i] = 2-(i%20)*0.1;
}
}
}
//[[## operation dotproduct()
double dotproduct(double* a, double* b, int length)
{
double result = 0;
int i = 0;
for (i = 0; i<length; i++)
result += a[i] * b[i];
return result;
}
int main( argc, argv )
int argc;
char **argv;
{
int processorID, numofProcessors;
int partialVectorSize ;
double t1, t2, localDotProduct, result;
MPI_Init( &argc, &argv );
MPI_Comm_size( MPI_COMM_WORLD, &numofProcessors );
MPI_Comm_rank( MPI_COMM_WORLD, &processorID );
if(processorID == 0)
t1 = MPI_Wtime();
// all processors constitute their own vector parts and
// calculates corresponding partial dot products
partialVectorSize = VECTORSIZE/ numofProcessors;
double *v1, *v2;
v1 = (double*)(malloc((partialVectorSize) * sizeof(double)));
v2 = (double*)(malloc((partialVectorSize) * sizeof(double)));
ConstructVectorPart(v1,0,partialVectorSize,1);
ConstructVectorPart(v2,0,partialVectorSize,2);
localDotProduct = dotproduct(v1,v2, partialVectorSize);
printf(" I am processor %d \n",processorID);
//----------------- code part 1 ---------------------------------------------
if( processorID != 0 ) // if not a master
{ // send partial result to master
MPI_Send( &localDotProduct, 1, MPI_DOUBLE, 0,0, MPI_COMM_WORLD );
}
else // master
{ // collect results
result = localDotProduct; // own result
int j;
for( j=1; j<numofProcessors; ++j )
{
MPI_Recv( &localDotProduct, 1, MPI_DOUBLE, j, 0, MPI_COMM_WORLD,MPI_STATUS_IGNORE);
result += localDotProduct;
}
t2 = MPI_Wtime();
printf(" result = %f TimeConsumed = %f \n",result, t2-t1);
}
//----------------------------------------------------------------------------
/*
//--------------------- code part 2 ----------------
MPI_Reduce(&localDotProduct, &result, 1, MPI_DOUBLE, MPI_SUM, 0,MPI_COMM_WORLD);
if(processorID == 0)
{
t2 = MPI_Wtime();
printf(" result = %f TimeConsumed = %f \n",result, t2-t1);
}
//---------------------------------------------------
*/
MPI_Finalize();
free(v1);
free(v2);
return 0;
}

Resources