0

I cannot understand why, in the following program, when a SIGINT signal arrives, the thread terminates directly (even if not covered by the signal handler). However, this does not happen in the main() process.

Signal handler:

volatile sig_atomic_t termina = 0;
static void sigHandler()
{
    termina = 1;
}

thread function:

static void *clientFun(void *fdSkt_comF)
{
    int fdSkt_com = *((int *) fdSkt_comF);
    char buffer[DIM_BUFFER];
    memset(buffer, '\0', DIM_BUFFER);

    //"termina" is set to 1 by the signal handler when a signal arrives
    while (termina == 0)
    {
        int lenghtRead;
        RETURN_SYSCALL(lenghtRead, read(fdSkt_com, buffer, DIM_BUFFER), "Errore: read(fdSkt_com, buffer, DIM_BUFFER)")

        if(lenghtRead == 0)
            break;

        //lenghtRead conta tutti i caretteri letti (compreso il '\0' se è presente)
        for(int i = 0; i < lenghtRead-1; i++)
        {
            buffer[i] = toupper((unsigned char) buffer[i]);
        }

        SYSCALL(writen(fdSkt_com, buffer, lenghtRead), "writen(fdSkt_com, buffer, lengthBuffer)")
    }
    puts("Ciao");
    return NULL;
}

where:

#define RETURN_SYSCALL(r,c,e) if((r=c)==-1) { perror(e);exit(errno); }
#define SYSCALL(c,e) if(c==-1) { perror(e);exit(errno);}

thread creation and detach:

pthread_t clientId;
THREAD_CREATE(&clientId, NULL, &clientFun, (void *) &fdSkt_com, "Thread setId")
SYSCALL_ZERO(pthread_detach(clientId) , "pthread_detach(&clientId)");

if you want to check all the code: server.c: https://pastebin.com/6BQA3mx6

client.c: https://pastebin.com/e42hKPxj

utils.h: https://pastebin.com/hLbySeFF

conn.h: https://pastebin.com/fL5cMxcg

QenBau
  • 157
  • 5
  • 15
  • 2
    As was said in your last post, your code is too big. Please post a smaller, readable snippet of code, so people can help you with your problem –  Aug 02 '21 at 11:41
  • 3
    `if (errno == EINTR) continue;` How do you determine that `errno` is not being set to EINTR? The read immediately restarts and you don't seem to have any way of detecting the value. Are you stepping through in a debugger to determine that the value is not as you expect? – William Pursell Aug 02 '21 at 11:41
  • 2
    Please reduce the code to a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – kaylum Aug 02 '21 at 11:45
  • I changed the question, I hope it is more understandable. – QenBau Aug 02 '21 at 11:59
  • 1
    For functions such as `read()` that indicate via their return value whether an error occurred, *always* check the return value first, and consult `errno` only if an error is indicated. In your case, one possibility is that the read returns successfully, presumably with a short count, after the being interrupted by the `SIGINT`. – John Bollinger Aug 02 '21 at 12:12
  • 1
    `RETURN_SYSCALL(lenghtRead, read(...) ...` is broken - `read()` does not return `NULL` or any other pointer-type value. – Andrew Henle Aug 02 '21 at 12:27
  • 1
    @SteveSummit: With `sigaction` you have to use the `SA_RESTART` flag to get the restart behavior, which is not the case in this program. You're right that under Linux, restartable handlers are the default when calling `signal`. – Nate Eldredge Aug 02 '21 at 14:13
  • I noticed that when you send, for example, the SIGINT signal, the thread ends. While if I put the same code as `clientFun()` in `main ()`, then EINTR is treated as normal. I can't understand why, as the signal handler is shared by the whole process – QenBau Aug 02 '21 at 20:08
  • I changed the question after the new discoveries. – QenBau Aug 02 '21 at 20:56
  • 1
    Function `sigHandler()` has the wrong signature for a signal handler. It must accept an argument of type `int`, even if it does not use it. Under some circumstances it would also need two other arguments, but I'm reasonably confident that yours are not such circumstances. That doesn't mean that the discrepancy is responsible for your issue, but it certainly should be responsible for some compiler warnings. – John Bollinger Aug 04 '21 at 17:12
  • 1
    In any case, I built a program with your signal handler and a lightly modified version of your thread function (it prints its upcased output to stdout), and set it up so that the thread was reading from /dev/random. When I sent that program a `SIGINT`, the thread broke from its loop, as evidenced by "Ciao" being printed. I conclude that the problem you are running into is related to something not presented in the question. – John Bollinger Aug 04 '21 at 17:39
  • 1
    Our general expectation is that questions requesting debugging assistance will present a [mre] demonstrating the issue. This question does not do so (and no previous version of it ever did). The exercise of preparing a good MRE frequently is sufficient in itself to reveal the issue, so it is worthwhile even when you don't plan to solicit assistance on here SO. – John Bollinger Aug 04 '21 at 17:46
  • I think the problem is that the thread is spawned in deatch mode: when I send the SIGINT signal, the main process exits the loop and terminates. In fact, if I put a `sleep()` after `pthread_detach(clientId)`, "Hello" is printed – QenBau Aug 04 '21 at 19:13
  • Anyway, how should I fix it by continuing to use `pthread_detach()` (assuming it's a problem)? – QenBau Aug 04 '21 at 19:18
  • 1
    @QenBau, detaching the thread has nothing to do with it. The example program I mentioned detaches the thread just like your program apparently does. – John Bollinger Aug 04 '21 at 20:31
  • 1
    @QenBau, if the main thread also recognizes a `SIGINT` as a request to terminate, however, then that may indeed explain your problem. When the main thread returns from the initial call to `main()`, or when any thread calls `exit()` or `_exit()`, the whole program terminates, including all threads. If you want to avoid that, the have the main thread terminate by calling `pthread_exit()`. – John Bollinger Aug 04 '21 at 20:35
  • The main thread also handles the `SIGINT` signal and exits the `while (ends == 0)` loop just like `clientFun()` - after the main thread exits the loop, it executes return 0. – QenBau Aug 04 '21 at 20:42

0 Answers0