Handling Signals and Message Queues for Inter-Process Communication

Handling Standard Signals

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void signal_handler(int sig_num) {
    if (sig_num == SIGINT) {
        printf("Ctrl+C signal received\n");
    }
}

int main(void) {
    // Set SIGINT to be ignored
    if (signal(SIGINT, SIG_IGN) == SIG_ERR) {
        perror("Failed to set SIG_IGN");
        exit(EXIT_FAILURE);
    }

    // Restore default behavior for SIGINT
    if (signal(SIGINT, SIG_DFL) == SIG_ERR) {
        perror("Failed to set SIG_DFL");
        exit(EXIT_FAILURE);
    }

    // Assign custom handler to SIGINT
    if (signal(SIGINT, signal_handler) == SIG_ERR) {
        perror("Failed to set custom handler");
        exit(EXIT_FAILURE);
    }

    while (1) {
        printf("Program is running...\n");
        sleep(2);
    }

    return 0;
}

Attempting to Modify SIGKILL Behavior

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void custom_handler(int sig_num) {
    if (sig_num == SIGINT) {
        printf("Interrupt signal caught\n");
    }
    if (sig_num == SIGKILL) {
        printf("SIGKILL signal intercepted\n");
    }
}

int main(void) {
    // These calls will fail as SIGKILL cannot be caught or ignored
    if (signal(SIGKILL, SIG_IGN) == SIG_ERR) {
        perror("Cannot ignore SIGKILL");
    }

    if (signal(SIGKILL, custom_handler) == SIG_ERR) {
        perror("Cannot handle SIGKILL");
    }

    if (signal(SIGKILL, SIG_DFL) == SIG_ERR) {
        perror("Cannot set SIGKILL default");
    }

    while (1) {
        printf("Process active\n");
        sleep(3);
    }

    return 0;
}

Reaping Zombie Processes Using SIGCHLD

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>

void child_handler(int sig_num) {
    if (sig_num == SIGCHLD) {
        // Reap all terminated child processes
        while (waitpid(-1, NULL, WNOHANG) > 0) {
            // Continue until no more children to reap
        }
    }
}

int main(void) {
    if (signal(SIGCHLD, child_handler) == SIG_ERR) {
        perror("Failed to set SIGCHLD handler");
        exit(EXIT_FAILURE);
    }

    // Create multiple child processes
    for (int i = 0; i < 8; i++) {
        pid_t child_pid = fork();
        if (child_pid == 0) {
            // Child process
            sleep(2);
            exit(0);
        }
    }

    // Parent process continues
    while (1) {
        pause(); // Wait for signals
    }

    return 0;
}

Simulating a Card Game with Alarm Signals

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void alarm_handler(int sig_num) {
    if (sig_num == SIGALRM) {
        printf("System played a random card\n");
        alarm(5); // Reset alarm
    }
}

int main(void) {
    if (signal(SIGALRM, alarm_handler) == SIG_ERR) {
        perror("Failed to set alarm handler");
        exit(EXIT_FAILURE);
    }

    alarm(5); // Initial alarm

    char user_card;
    while (1) {
        printf("Enter your card: ");
        scanf("%c", &user_card);
        getchar(); // Consume newline

        printf("You played: %c\n", user_card);
        alarm(5); // Reset timer after user input
    }

    return 0;
}

Testing Signal Tranmsission Functions

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void user_signal_handler(int sig_num) {
    if (sig_num == SIGUSR1) {
        printf("Received SIGUSR1\n");
        raise(SIGKILL); // Self-terminate
    }
}

int main(void) {
    if (signal(SIGUSR1, user_signal_handler) == SIG_ERR) {
        perror("Failed to set SIGUSR1 handler");
        exit(EXIT_FAILURE);
    }

    pid_t pid = fork();

    if (pid > 0) {
        // Parent process
        while (1) {
            printf("Parent process alive\n");
            sleep(2);
        }
    } else if (pid == 0) {
        // Child process
        sleep(5);
        printf("Child process declaring independence\n");
        kill(getpid(), SIGUSR1); // Send signal to self

        // This code won't execute due to SIGKILL
        while (1) {
            printf("Child continues\n");
            sleep(2);
        }
    }

    return 0;
}

Implementing Message Queues

Message Sender

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>

struct message_buffer {
    long msg_type;
    char msg_content[1024];
};

#define MSG_DATA_SIZE (sizeof(struct message_buffer) - sizeof(long))

int main(void) {
    key_t queue_key;
    if ((queue_key = ftok("/tmp", 'A')) == -1) {
        perror("ftok failed");
        exit(EXIT_FAILURE);
    }
    printf("Generated key: 0x%x\n", queue_key);

    int queue_id;
    if ((queue_id = msgget(queue_key, IPC_CREAT | 0666)) == -1) {
        perror("msgget failed");
        exit(EXIT_FAILURE);
    }
    printf("Queue ID: %d\n", queue_id);

    struct message_buffer send_buf;
    while (1) {
        memset(send_buf.msg_content, 0, sizeof(send_buf.msg_content));

        printf("Enter message type: ");
        scanf("%ld", &send_buf.msg_type);
        getchar();
        printf("Enter message: ");
        fgets(send_buf.msg_content, sizeof(send_buf.msg_content), stdin);
        send_buf.msg_content[strlen(send_buf.msg_content) - 1] = '\0';

        if (msgsnd(queue_id, &send_buf, MSG_DATA_SIZE, 0) == -1) {
            perror("msgsnd failed");
            exit(EXIT_FAILURE);
        }
        printf("Message sent\n");

        if (strcmp(send_buf.msg_content, "exit") == 0) {
            break;
        }
    }

    return 0;
}

Message Receiver

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>

struct message_buffer {
    long msg_type;
    char msg_content[1024];
};

#define MSG_DATA_SIZE (sizeof(struct message_buffer) - sizeof(long))

int main(void) {
    key_t queue_key;
    if ((queue_key = ftok("/tmp", 'A')) == -1) {
        perror("ftok failed");
        exit(EXIT_FAILURE);
    }
    printf("Generated key: 0x%x\n", queue_key);

    int queue_id;
    if ((queue_id = msgget(queue_key, IPC_CREAT | 0666)) == -1) {
        perror("msgget failed");
        exit(EXIT_FAILURE);
    }
    printf("Queue ID: %d\n", queue_id);

    struct message_buffer recv_buf;
    while (1) {
        memset(recv_buf.msg_content, 0, sizeof(recv_buf.msg_content));

        if (msgrcv(queue_id, &recv_buf, MSG_DATA_SIZE, 1, 0) == -1) {
            perror("msgrcv failed");
            exit(EXIT_FAILURE);
        }
        printf("Received: %s\n", recv_buf.msg_content);

        if (strcmp(recv_buf.msg_content, "exit") == 0) {
            break;
        }
    }

    return 0;
}

Tags: Linux signals IPC Message Queues Process Management

Posted on Tue, 04 Aug 2026 16:58:24 +0000 by phyzar