Вопрос

I have encountered problems on signal handling when writing a shell-like program on C.
Here is the simplified version of my code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#define SIZE 255

void sig_handler(int sig){
if (sig == SIGINT)
    printf("\n[shell]$\n");
}

int main()
{
    char input[SIZE];
    printf("[shell]$");
    signal(SIGINT,sig_handler);
    while( gets(input) != NULL ){
    // code of the shell including command interpreter and command execution
        printf("[shell]$");
    }
    return 0;
}

When I run the program and try out SIGINT with command - "cat", the output shows as the following:

[shell]$ ^C  (ctrl+C pressed for the first time)
[shell]$     
^C           (the input position go to the next line, which is unwanted)
[shell]$
cat          (I want it in the same line with [shell]$)
^C
[shell]$
[shell]$     (duplicate printing occurs)

I have tried to modify the function void sig_handler(int sig) by deleting the second \n. However, the situation becomes worse than before. The program doesn't automatically trigger the signal event on the first pressing of ctrl+C.

To clarify my problem, here are the two questions I ask:
1. How to make the input position on the same line with [shell]$ ?
2. How to solve the duplicate printing problem ?

Это было полезно?

Решение

What @zneak said is true, you can use fflush and delete the second \n in sig_handler,

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#define SIZE 255

void sig_handler(int sig){
if (sig == SIGINT)
    printf("\n[shell]$");
    fflush(stdout);
}

int main()
{
    char input[SIZE];
    printf("[shell]$");
    fflush(stdout);
    signal(SIGINT,sig_handler);
    while( gets(input) != NULL ){
    // code of the shell including command interpreter and command execution
        printf("[shell]$");
    }
    return 0;
}

Другие советы

First and foremost, printing from signal handler is a bad idea. Signal handler is like an interrupt handler - it happens asynchronously, it could be raised while being inside your standard library code and calling another stdlib routine might mess up with non-reentrant internals of it (imagine catching SIGINT while inside of printf() in your loop).

If you really want to output something from within, you better use raw write() call to stderr file descriptor.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top