'Program with two process and pipes stays in a while loop reading
I'm making a program to simulate a miner (blockchain) for a college project and I have two processes a monitor that checks if the solution found is correct and the miner which tries solutions, and I communicate them using pipes, the problem is that the one reading in Monitor stays in the loop and never ends the process, if you could help me with this, thanks in regards.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "pow.h"
#define MAX_THREADS 100
long int result;
typedef struct minero
{
long int starting;
long int ending;
long int objective;
} mine_args;
void thread_killer(pthread_t *thread, int n_threads)
{
int i, error;
for (i = 0; i < n_threads; i++)
{
pthread_cancel(thread[i]);
error = pthread_join(thread[i], NULL);
if (error != 0)
{
fprintf(stderr, "pthread_join: %s\n", strerror(error));
exit(EXIT_FAILURE);
}
}
}
void *mine(void *arg)
{
mine_args *mine_data = (mine_args *)arg;
long int i;
for (i = mine_data->starting; i < mine_data->ending; i++)
{
/* para forzar error usar ./minero 3 5 3 y descomentar */
/* if (mine_data->objective == 42453944)
{
result = 0;
break;
} */
if (pow_hash(i) == mine_data->objective)
{
result = i;
break;
}
}
return NULL;
}
int main(int argc, char *argv[])
{
int accepted;
int rondas, threads, i, j, error;
int status_minero, status_monitor;
int pipe_tomonitor[2];
int pipe_monitor_status;
int pipe_tominero[2];
int pipe_minero_status;
long int obj;
pid_t pid_monitor, pid_minero;
ssize_t nbytes, nbytes_w, nbytes_r;
if (argc != 4)
{
fprintf(stderr, "Arguments: # rounds, # threads and objective");
return EXIT_FAILURE;
}
/* guardamos los arguments */
obj = atoi(argv[1]);
rondas = atoi(argv[2]);
threads = atoi(argv[3]);
if (threads > MAX_THREADS)
{
fprintf(stderr, "Exceeded maximum number of threads (%i)\n", MAX_THREADS);
return EXIT_FAILURE;
}
pthread_t thread[threads];
mine_args minerostruct[threads];
if (obj > POW_LIMIT)
{
fprintf(stderr, "Exceeded the maximum number for the objective (%i)\n", POW_LIMIT);
return EXIT_FAILURE;
}
/* Create a pipe from monitor to minero */
pipe_minero_status = pipe(pipe_tominero);
if (pipe_minero_status == -1)
{
perror("pipe");
exit(EXIT_FAILURE);
}
/* Create a pipe from minero to monitor */
pipe_monitor_status = pipe(pipe_tomonitor);
if (pipe_monitor_status == -1)
{
perror("pipe");
exit(EXIT_FAILURE);
}
/* fork para el monitor */
pid_monitor = fork();
if (pid_monitor < 0)
{
perror("fork");
exit(EXIT_FAILURE);
}
/****************************/
/* PROCESO MONITOR */
/****************************/
else if (pid_monitor == 0)
{
/* Cerramos lectura desde el monitor */
close(pipe_tominero[0]);
/* Cerramos escritura */
close(pipe_tomonitor[1]);
fprintf(stdout, "monitor proc: %i\n", getpid());
do
{
nbytes_r = read(pipe_tomonitor[0], &obj, sizeof(obj));
if (nbytes_r == -1)
{
perror("read");
exit(EXIT_FAILURE);
}
if (nbytes_r == 0)
{
exit(EXIT_SUCCESS);
}
nbytes_r = read(pipe_tomonitor[0], &result, sizeof(result));
if (nbytes_r == -1)
{
perror("read");
exit(EXIT_FAILURE);
}
if (nbytes_r == 0)
{
exit(EXIT_SUCCESS);
}
if (nbytes_r > 0)
{
if (pow_hash(result) == obj)
{
fprintf(stdout, "Solution accepted: %08ld --> %08ld\n", obj, result);
/* Le decimos que ha sido aceptada la solucion */
accepted = 1;
nbytes_w = write(pipe_tominero[1], &accepted, sizeof(accepted));
if (nbytes_w == -1)
{
perror("write");
exit(EXIT_FAILURE);
}
}
else
{
fprintf(stdout, "Solution rejected: %08ld !-> %08ld\n", obj, result);
/* Le decimos que NO ha sido aceptada la solucion */
accepted = -1;
nbytes_w = write(pipe_tominero[1], &accepted, sizeof(accepted));
if (nbytes_w == -1)
{
perror("write");
exit(EXIT_FAILURE);
}
}
}
fprintf(stdout, "bytes: %li\n", nbytes_r);
if (nbytes_r == 0)
{
exit(EXIT_SUCCESS);
}
} while (nbytes_r != 0);
/* Cerramos los pipes */
close(pipe_tomonitor[0]);
close(pipe_tominero[1]);
fprintf(stdout, "aqui");
fflush(stdout);
exit(EXIT_SUCCESS);
}
/* fork para el minero */
pid_minero = fork();
if (pid_minero < 0)
{
perror("fork");
exit(EXIT_FAILURE);
}
/****************************/
/* PROCESO MINERO */
/****************************/
else if (pid_minero == 0)
{
/* Cerramos escritura */
close(pipe_tominero[1]);
/* Cerramos lectura */
close(pipe_tomonitor[0]);
fprintf(stdout, "minero proc: %i\n", getpid());
/* rondas */
for (i = 0; i < rondas; i++)
{
for (j = 0; j < threads; j++)
{
minerostruct[j].objective = obj;
minerostruct[j].starting = floor(0 + (POW_LIMIT / threads) * (j));
minerostruct[j].ending = ceil(0 + (POW_LIMIT / threads) * (j + 1));
/*fprintf(stdout, "Minero %i obj: %li start: %li ending: %li\n", j, minerostruct[j].objective, minerostruct[j].starting, minerostruct[j].ending);
*/
error = pthread_create(&thread[j], NULL, mine, (void *)&minerostruct[j]);
if (error != 0)
{
fprintf(stderr, "pthread_create: %s\n", strerror(error));
exit(EXIT_FAILURE);
}
}
thread_killer(thread, threads);
/* fprintf(stdout, "Obj: %08ld => Res: %08ld\n", obj, result);
fflush(stdout); */
/* Le mandamos el objetivo al monitor */
nbytes = write(pipe_tomonitor[1], &obj, sizeof(obj));
if (nbytes == -1)
{
perror("write");
exit(EXIT_FAILURE);
}
/* Le mandamos el resultado al monitor */
nbytes = write(pipe_tomonitor[1], &result, sizeof(result));
if (nbytes == -1)
{
perror("write");
exit(EXIT_FAILURE);
}
nbytes = read(pipe_tominero[0], &accepted, sizeof(accepted));
if (nbytes == -1)
{
perror("read");
exit(EXIT_FAILURE);
}
if (accepted < 0)
{
fprintf(stdout, "The solution has been invalidated\n");
exit(EXIT_FAILURE);
}
obj = result;
}
/* Cerramos los pipes */
close(pipe_tominero[0]);
close(pipe_tomonitor[1]);
exit(EXIT_SUCCESS);
}
if (waitpid(pid_minero, &status_minero, 0) == -1)
{
perror("waitpid");
return EXIT_FAILURE;
}
if (WIFEXITED(status_minero))
{
const int s_minero = WEXITSTATUS(status_minero);
printf("Minero exited with status %d\n", s_minero);
}
if (waitpid(pid_monitor, &status_monitor, 0) == -1)
{
perror("waitpid");
return EXIT_FAILURE;
}
if (WIFEXITED(status_monitor))
{
const int s_monitor = WEXITSTATUS(status_monitor);
printf("Monitor exited with status %d\n", s_monitor);
}
exit(EXIT_SUCCESS);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
