The program consists of 2 parts (i was asked to use pipe): A. manager - that creates processes that will help him calculate how many instances of a particular char are in the file. B. Count - Calculates how many instances there are in the file and returns the pipe to the manager. Moreover, In each program I changed the behavior of SIGPIPE, and changed the behavior I desired.
in the manager.c:
for(i = 0; i < len_sym; i++){
...
if (pipe(pipe_fds + (2 * i)) == -1) {
perror("ERROR : Failed creating pipe");
exit(EXIT_FAILURE);
}
if ((curr_child = fork()) == 0){ //son
dup2(pipe_fds[2*i + 1], STDOUT_FILENO);
close(pipe_fds[2*i + 1]);
close(pipe_fds[2*i + 0]);
execvp(child_args[0], child_args);
}
else { //parent
if (curr_child == -1){
exit(EXIT_FAILURE);
}
close(pipe_fds[2*i + 1]); // close writerfd
child_pids[i] = curr_child;
printf("%d son created with pid %d\n", i + 1, child_pids[i]);
// if (i == 1) {
// kill(curr_child, SIGPIPE);
// }
}
}
for(i = 0; i < len_sym; i++){
curr_child = waitpid(child_pids[i], &exit_code, 0);
printf("exit code %d\n", exit_code);
printf("child pid %d\n", curr_child);
if (curr_child == -1 || 256 == exit_code) {
exit(EXIT_FAILURE);
}
if (WIFEXITED(exit_code)) {
int bytes_read;
while ((bytes_read = read(pipe_fds[i*2 + 0], buff, BUFF_SIZE)) > 0) {
buff[bytes_read] = '\0';
printf("%s", buff);
}
if (bytes_read == -1) {
perror("ERROR : Failed reading from fifo");
close(pipe_fds[i*2 + 0]);
exit(EXIT_FAILURE);
}
close(pipe_fds[i*2 + 0]);
child_pids[i] = 0;
}
}
handling SIGPIPE in manager.c
void my_signal_handler(int signum) {
switch (signum) {
case SIGPIPE:
printf("SIGPIPE for Manager process %d. Leaving\n", getpid());
for (int i = 0; i < len_sym; i++) {
if ((child_pids != NULL) && child_pids[i]) {
kill(child_pids[i], SIGTERM);
}
}
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
void register_signal_handlin() {
struct sigaction new_action;
memset(&new_action, 0, sizeof(new_action));
new_action.sa_handler = my_signal_handler;
if (0 != sigaction(SIGPIPE, &new_action, NULL)) {
exit(EXIT_FAILURE);
}
}
in the count.c:
for (j = 0; j < file_length; j++){
if (*temp++ == c){
counter++;
}
}
sleep(10);
if (argc > 4){
sprintf(buff, "Process %d finishes. Symbol %c. Instances %d.\n", getpid(), c, counter);
int buff_len = strlen(buff);
int bytes_written;
while ((bytes_written = write(writerfd, p, buff_len)) > 0) {
p += bytes_written;
buff_len -= bytes_written;
}
if (bytes_written == -1) {
perror("PROCESS ERROR : Failed writing to fifo");
close(writerfd);
return EXIT_FAILURE;
}
close(writerfd);
}
handling SIGPIPE in count.c
void my_signal_handler(int signum) {
switch (signum) {
case SIGPIPE:
printf("SIGPIPE for process %d. Symbol %c. Counter %d.\n", getpid(), c, counter);
exit(EXIT_FAILURE);
case SIGTERM:
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
void register_signal_handling() {
struct sigaction new_action;
memset(&new_action, 0, sizeof(new_action));
new_action.sa_handler = my_signal_handler;
if (0 != sigaction(SIGPIPE, &new_action, NULL)) {
exit(EXIT_FAILURE);
}
if (0 != sigaction(SIGTERM, &new_action, NULL)) {
exit(EXIT_FAILURE);
}
}
So in fact I run the manger program, and at the same time opens a new terminal, and from it sends kill -13 to a particular process.
the problems:
In the manager I get an exit code of 256. Why?
The WIFSIGNALED flag does not turn on, although I have sent a signal to the process.
The return from the waitpid function is not -1, but the process number I sent kill -13 from the second terminal.
I tried to send kill to one of the children from the manager and for some reason he activates the signal handler of the manager rather than the child's signal handler.
I am in the process of learning OS, so I will be happy for any help.