169 похожих чатов

Https://Pastebin.Com/8bSEmdVu Подскажите почему код не завершается при подаче sigterm?

7 ответов

42 просмотра

Причина, по которой ваш код может завершиться неправильно при получении сигнала SIGTERM, может быть связана с использованием Accept в основном цикле. После получения сигнала SIGTERM вы устанавливаете выходной флаг в 1, но функция принятия блокируется и ожидает нового соединения. Это может привести к зависанию программы. Чтобы решить эту проблему, вы можете использовать неблокирующий подход к вызову принятия и добавить механизм разрыва цикла при получении сигнала SIGTERM. Вот модифицированная версия вашего кода с этими изменениями:

#include <iostream> #include <cstring> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <thread> #include <vector> #include <signal.h> constexpr int PORT = 5555; class msg { public: int from; int to; char text[1024]; }; volatile sig_atomic_t exitFlag = 0; // Завершение программы void signalHandler(int signum) { std::cout << "Received signal " << signum << std::endl; exitFlag = 1; } // Создаем таблицу подключенных устройств std::vector<std::tuple<int, int>> client_member; // Функция для обработки каждого клиента в отдельном потоке void handleClient(int clientSocket) { char buffer[1024]; // Запись клиента в таблицу подключенных устройств int bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0); std::tuple<int, int> temp{std::atoi(buffer), clientSocket}; client_member.push_back(temp); for (int i = 0; i < client_member.size(); i++) { std::cout << "id: " << std::get<0>(client_member.at(i)) << " socket: " << std::get<1>(client_member.at(i)) << std::endl; } while (!exitFlag) { // Получаем данные от клиента куда направить сообщение int bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0); if (bytesRead <= 0) { break; } int to = atoi(buffer); // Получаем данные от клиента само сообщение bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0); if (bytesRead <= 0) { break; } buffer[bytesRead] = '\0'; // Выводим полученные данные от клиента в консоль сервера std::cout << "Received from client: " << buffer << " Client socket: " << clientSocket << std::endl; // Отправляем сообщение for (int i = 0; i < client_member.size(); i++) { if (std::get<0>(client_member.at(i)) == to) { send(std::get<1>(client_member.at(i)), buffer, strlen(buffer), 0); } } } // Удаляем отключившегося клиента for (auto it = client_member.begin(); it < client_member.end(); it++) { if (std::get<1>(*it) == clientSocket) { client_member.erase(it); } } // Закрываем сокет клиента после завершения обмена данными close(clientSocket); } int main() { // Создаем сокет сервера int serverSocket = socket(AF_INET, SOCK_STREAM, 0); if (serverSocket == -1) { std::cerr << "Error creating socket\n"; return -1; } sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(PORT); serverAddr.sin_addr.s_addr = INADDR_ANY; // Привязываем сокет к адресу и порту if (bind(serverSocket, reinterpret_cast<struct sockaddr*>(&serverAddr), sizeof(serverAddr)) == -1) { std::cerr << "Error binding to port\n"; close(serverSocket); return -1; } // Слушаем входящие соединения if (listen(serverSocket, 5) == -1) { std::cerr << "Error listening on socket\n"; close(serverSocket); return -1; } std::cout << "Server listening on port: " << PORT << std::endl; std::vector<std::thread> clientThreads; signal(SIGTERM, signalHandler); while (!exitFlag) { sockaddr_in clientAddr; socklen_t clientAddrSize = sizeof(clientAddr); // Принимаем входящее соединение от клиента (non-blocking) int clientSocket = accept(serverSocket, reinterpret_cast<struct sockaddr*>(&clientAddr), &clientAddrSize); if (clientSocket == -1) { if (errno == EWOULDBLOCK || errno == EAGAIN) { // No incoming connection, continue continue; } else { std::cerr << "Error accepting connection\n"; close(serverSocket); return -1; } } // Запускаем новый поток для обработки клиента std::thread clientThread(handleClient, clientSocket); clientThreads.push_back(std::move(clientThread)); }

for (auto& thread : clientThreads) { thread.join(); // Ждем завершения всех потоков } // Закрываем сокет сервера close(serverSocket); return 0; }

нет бы поблагодарить

ÅÑGÈLØK
нет бы поблагодарить

так скинь ссылку на чат, там и скажем

Похожие вопросы

Обсуждают сегодня

30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
в JclConsole объявлено так: function CtrlHandler(CtrlType: DWORD): BOOL; stdcall; - где ваше объявление с stdcall? у вас на картинке нет stdcall
Karagy
8
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
~ 2m21s  nix shell github:nixos/nixpkgs#stack ~  stack ghc -- --version error: … while calling the 'derivationStrict' builtin at /builtin/derivation.nix:...
Rebuild your mind.
6
Карта сайта