Reputation: 23
I have a Client-Server application written in C language. This is not a professional poject, so everything I do is from command line (ubuntu terminal). Whenever the client code requires an input from the user, I use an fgets to take said input. The problem is that if the user wants to stop the input process and exit the server by sending a CTRL+C signal (SIGINT), this won't work.
Specifically, what happens is this:
Therefore, the connection is stuck and the client is forever stopped in this input operation.
I don't know how to fix this. What i want is my client code to ask for input, if the user presses CTRL+C then the client code MUST stop and send such kill signal to the server. How can I do that?
I also tried with scanf like this:
while ((scanf("%s", buff)) == -1) EINTR_ABORT("Errore di scanf");
getchar();
(I know I should never use scanf, but for some reason my professor is fine with it -and I know is kinda sad but whatever-)
This is my fgets:
if(fgets(buff_ID, sizeof(buff_ID), stdin)== NULL)
EINTR_ABORT("Errore di fgets");
Where this is EINTR_ABORT:
#define ISTANT_ABORT(warning) ({ \
fprintf(stderr, "%s: %s.\n", warning, strerror(errno)); \
exit(EXIT_FAILURE);\
})
#define EINTR_ABORT(warning) ({ \
if(errno != EINTR) \
ISTANT_ABORT(warning); \
})
My professor never pointed this issue out, but he (obviously, because why not after all) expects us to solve it on our own in this project. I tried my best and never worked out anything that would actually fix the issue.
Upvotes: 0
Views: 514
Reputation: 1843
You can handle INT signal and set a flag signalling that user interrupted input.
#include <stdio.h>
#include <signal.h>
static sig_atomic_t interrupted = 0;
static void sigint_handler(int)
{
interrupted = 1;
}
int main(void)
{
struct sigaction act;
act.sa_handler = sigint_handler; // Set new SIGINT handler
sigemptyset(&act.sa_mask); // No need to mask signals in handler
act.sa_flags = 0; // Don't set SA_RESTART flag
if (sigaction(SIGINT, &act, NULL) != 0)
perror("sigaction");
char str[256];
char *ret = fgets(str, sizeof(str), stdin);
if (interrupted)
{
// Handle interrupt here
printf("Interrupted!\n");
} else if (ret)
{
// Handle fgets result here
}
return 0;
}
Note: don't use signal()
function for setting up signal handler because on Linux it applies SA_RESTART
flag.
Upvotes: 1