Ryan Otweeng
Ryan Otweeng

Reputation: 81

C - Signal handlers and Kill() not working to communicate through 2 processes

As an assignment I got at my university to send arguments to Server, then server needs to calculate and send the result back to the Client. I need to make 2 .c files(client and server). Then, compile them using gcc command(gcc client.c -o client.out) and run the server first, let it run in the background(CTRL+Z), get it's PID('ps' command) and then run the client with those arguments:

enter image description here

The code is written in C, and my workspace is Linux terminal using Putty. The problem is that when I use the "kill" command in my client file(I called it "c.c") in order to send a signal to a specific process that I have it's PID(which is the server) , The handler of the server doesn't wake up and start working and of course because of that, it won't send a "kill" command back to the client with result. Jokes aside, I literally sat 24 hours(I'm mean.. for real lol), and since it's 5am I really need to get some rest I'm starting to get delusional and I have less then 24 hours to submit the assignment :( . Below I shared my code, I hope it's understandable, I tried to do my best guys.

Client.c:

#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#define GODEL 100

char* reqArgs[5];

void sigterm_handler(int dummy)
{
    char msg[150];
    int clientPID, toClientFD, res, signalCharsR;
    pid_t pid;
    clientPID = getpid();

    char* toClientFileName = (char*)malloc(strlen("to_client_") + strlen(reqArgs[4]) + strlen(".txt") + 1);
    strcat(toClientFileName, "to_client_");
    strcat(toClientFileName, reqArgs[4]);
    strcat(toClientFileName, ".txt");

    // Open the result file(to_client_XXXXX) from Server
    toClientFD = open(toClientFileName, O_RDONLY, 0777);
    if(toClientFD == -1)
    {
        sprintf(msg, "Could not Open file: to_client_%d.txt\n", clientPID);
        write(2, msg, strlen(msg));
        exit(-1);
    }

    // Read the result from the results file(to_client_XXXXX)
    signalCharsR = read(toClientFD, msg, strlen(toClientFileName));
    if(signalCharsR == -1)
    {
        sprintf(msg, "Could not Read result from file: to_client_%d.txt\n", clientPID);
        write(2, msg, strlen(msg));
        exit(-1);
    }

    write(1, msg, sizeof(msg));

    signal(SIGTERM, sigterm_handler);
    
    exit(0);
}

int main(int argc, char* argv[])
{
    char msg[150];
    int logFD, reqFD, charsR = 0;
    pid_t pid;
    
    if(argc != 5)
    {
        strcpy(msg, "Wrong number of arguments\n");
        write(2, msg, strlen(msg));
        exit(-1);
    }

    signal(SIGTERM, sigterm_handler);

    for(int i = 0; i<argc; i++)
        reqArgs[i] = argv[i];

    // Open request.txt, Creates it if doesn't exist
    reqFD = open("request.txt", O_CREAT | O_RDONLY | O_WRONLY | O_APPEND, 0777);
    if(reqFD == -1)
    {
        strcpy(msg, "Could not Create and Open file: request.txt\n");
        write(2, msg, strlen(msg));
        exit(-1);
    }

    // Open cLog.txt file
    logFD = open("cLog.txt", O_CREAT | O_RDONLY | O_WRONLY | O_APPEND, 0777);
    if(logFD == -1)
    {
        strcpy(msg, "Could not Create and Open file: request.txt\n");
        write(2, msg, strlen(msg));
        exit(-1);
    }
    close(1);
    dup(logFD);
    close(logFD);
    
    // Writing into request.txt
    for(int i = 2; i<argc; i++)
    {
        charsR = write(reqFD, argv[i], strlen(argv[i]));
        if(charsR == -1)
        {
            strcpy(msg, "Could not write to file: request.txt\n");
            write(2, msg, strlen(msg));
            exit(-1);
        }
        write(reqFD, "\n", 1);
    }
    char mypid[5];
    sprintf(mypid, "%d", pid);
    write(reqFD, mypid, sizeof(mypid));
    close(reqFD);
    
    signal(SIGTERM, sigterm_handler);

    // Sending KILL to the Server
    if(kill(atoi(argv[1]), SIGTERM) == -1){
        write(2, "Could not send signal\n", strlen("Could not send 
        signal\n"));
    }
    
    // Sleeping until Server sends back a result
    while(1){
        sleep(1);
    }

    exit(1);
}

Server:

#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>

int calculator(int x, int y, int op)
{
    switch(op)
    {
        case 1:
            return x+y;
            break;
        case 2:
            return x-y;
            break;
        case 3:
            return x*y;
            break;
        case 4:
            if(y == 0)
                return -1;
            return x/y;
            break;
        default:
            return -1;
    }
    return -1;
}

void sigterm_handler(int dummy)
{
    char msg[150];
    pid_t pid;

    // Forking
    pid = fork();
    if(pid < 0)
    {
        //printf("EX2_FROM_ERROR\n");
        strcpy(msg, "Could not Fork\n");
        write(2, msg, strlen(msg));
        printf("Could not Fork\n");
        exit(-1);
    }
    else
    {
        // Son
        if(pid == 0)
        {
            int logFD, fd, bytesRead, x, y, op, res;
            char ch;
            char* reqArgs[4];

             // Open request.txt file
            fd = open("request.txt", O_RDONLY, 0777);
            if(fd == -1)
            {
                strcpy(msg, "Could not open file: request.txt\n");
                write(2, msg, strlen(msg));
                exit(-1);
            }

            //  Reading lines from request.txt file;
            for(int i = 0; i < 4; i++) {
                int j = 0;
                bytesRead = read(fd, &ch, 1);

                    while(ch != '\n' && bytesRead != 0) {
                    reqArgs[i][j] = ch;
                    bytesRead = read(fd, &ch, 1);
                    j++;
                }
                reqArgs[i][j] = '\0'; // put null at the end
            }
            close(fd);  // Close request.txt File


            // Initialize the data into variables
            x = atoi(reqArgs[0]);
            op = atoi(reqArgs[1]);
            y = atoi(reqArgs[2]);
            printf("%d+%d+%d=", x, op, y);


            // Creating result file to send to the client
            char* toClientFileName = (char*)malloc(strlen("to_client_") + strlen(reqArgs[3]) + strlen(".txt") + 1);
            strcat(toClientFileName, "to_client_");
            strcat(toClientFileName, reqArgs[3]);
            strcat(toClientFileName, ".txt");

            fd = open(toClientFileName, O_CREAT | O_RDWR | O_APPEND, 0777);
            if(fd == -1)
            {
                sprintf(msg, "Could not Create and Open file: %s\n", toClientFileName);
                write(2, msg, strlen(msg));
                //printf("Could not Create and Open file: %s\n", toClientFileName);
                exit(-1);
            }


            // Calling the calc() function
            res = calculator(x, y, op);
            if(res =! -1)
                write(fd, &res, sizeof(res));
            else
                write(fd, "Calculate went wrong\n", strlen("Calculate went wrong")+1);

            close(fd);
            signal(SIGTERM, sigterm_handler);

            char test[5];
            sprintf(test, "%d", atoi(reqArgs[3]));
            // Sending KILL back to the Client
            if(kill(atoi(test), SIGTERM) == -1){
                 write(2, "Could not send signal\n", strlen("Could not send 
                 signal\n"));
            }
        }
        // Father
        else
        {
            
        }
    }
    signal(SIGTERM, sigterm_handler);
}

int main(int argc, char* argv[])
{
    signal(SIGTERM, sigterm_handler);

    while(1){
        sleep(10);
    }

    exit(1);
}

Upvotes: 1

Views: 1176

Answers (1)

phunsoft
phunsoft

Reputation: 2735

ctrl-z merely stops the forground process. It does not send it to the background. You need to resume the process as background process using bg $n where n is the job number shown in brackets after you stopped the server, [1] as seen in your terminal screenshot:

bg $1

Upvotes: 1

Related Questions