4
votes

I'm doing a project for university, a chat system with a server and multiple clients.

In the specification document there is written:

The main thread does a controlled loop on the global var go, and at each cycle waits for a connection request by an user

And also:

Server stops with SIGTERM or SIGINT. When signal is received, the global var go is set to zero, and all threads exit from the loop cycle

So, the thread main create the socket, bind the port and at every new connection does an accept() and create a thread worker which takes care of the communication with the client.

My problem is exiting the thread main only changing the global var. In the thread main if I do

while (go && accept(params)) {}

it doesn't enter in the while loop.

So at the moment the code is

while (go) {
    accept(params);
    // Do stuff
}

And, well, when I set go to zero it waits on accept, so I have to create a new connection, it accepts the connection and then exit the thread 'cause go becomes zero.

Same problem with thread worker

while (go && read(socket_id, buffer, sizeof(char)) > 0) {}

It waits for a char from the socket to exit the loop.

I don't see a way to exit loops using only the go var. I think I've to close the socket, or find another way, am I wrong?

I'm not interested in other ways to exit threads, just to know if it's possible to exit loops just changing the go var

Thanks!

1
listen doesn't block. Did you mean accept? - user253751
@immibis right, sorry, let me update the question. Done - rpadovani
How do you toggle go? - alk
@alk I've a signal handler in the main() function. It works well, because when I set it to 0 others while(go) (that don't have an accept or a read inside) exit - rpadovani

1 Answers

2
votes

Assuming you setup a signal handler for SIGINT and SIGTERM to toggle the go to !=0 you also want to unset the SA_RESTART flag for the handler(s), which would make accept() return -1 on the signal's reception.

To do so setup the signal handler using sigaction(). For the struct sigaction you pass in do not set the member sa_flags to hold SA_RESTART.

For a detailed description which system call is influenced by the SA_RESTART flag see section "Interruption of system calls and library functions by signal handlers" of man 7 signal.


Independendly from this make sure go is defined sig_atomic_t.