Location>code7788 >text

c++ deadlock debugging , gdb pstack

Popularity:987 ℃/2024-12-19 20:39:47
#include <iostream> #include <cstring> #include <> #include <sys/> #include <netinet/in.h> #include <arpa/> #include <> #include <> #include <cstdlib> #include <> #include <> // Define two mutually exclusive locks pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; // Functions that handle client requests void* handle_client(void* arg) { int client_socket = *(static_cast<int*>(arg)); free(arg); // Release dynamically allocated memory passed to a thread std::cout << "Client connected with socket: " << client_socket << std::endl; // Simulate client request processing if (client_socket == 4) { // Client 1: get mutex1, then get mutex2 std::cout << "Client " << client_socket << ": Trying to lock mutex1..." << std::endl; pthread_mutex_lock(&mutex1); usleep(5000000); // Hibernate 5 seconds std::cout << "Client " << client_socket << ": Locked mutex1, now trying to lock mutex2..." << std::endl; // Trying to get mutex2 pthread_mutex_lock(&mutex2); // deadlock point usleep(5000000); // Hibernate 5 seconds std::cout << "Client " << client_socket << ": Locked both mutex1 and mutex2" << std::endl; // Releasing a Mutual Exclusion Lock pthread_mutex_unlock(&mutex2); pthread_mutex_unlock(&mutex1); } else if (client_socket == 5) { // Client 2: get mutex2 first, then mutex1 std::cout << "Client " << client_socket << ": Trying to lock mutex2..." << std::endl; pthread_mutex_lock(&mutex2); usleep(5000000); // Hibernate 5 seconds std::cout << "Client " << client_socket << ": Locked mutex2, now trying to lock mutex1..." << std::endl; // Trying to get mutex1 pthread_mutex_lock(&mutex1); // deadlock point usleep(5000000); // Hibernate 5 seconds std::cout << "Client " << client_socket << ": Locked both mutex1 and mutex2" << std::endl; // Releasing a Mutual Exclusion Lock pthread_mutex_unlock(&mutex1); pthread_mutex_unlock(&mutex2); } // Closing a client connection close(client_socket); std::cout << "Client disconnected with socket: " << client_socket << std::endl; pthread_exit(NULL); } // TCP Server Master Functions void start_server(int port) { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); // Creating a socket file descriptor if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // Setting the SO_REUSEADDR option if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) { perror("setsockopt failed"); exit(EXIT_FAILURE); } // Bind the socket to the specified port address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(port); if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // monitor a connection if (listen(server_fd, 3) < 0) { perror("listen failed"); exit(EXIT_FAILURE); } std::cout << "Server started on port " << port << ". Waiting for connections..." << std::endl; int client_id = 1; // Used to distinguish between different clients while (true) { // Accepting new client connections if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) { perror("accept failed"); continue; } // Create a new thread for each client pthread_t thread; int* client_socket_ptr = new int(new_socket); // Dynamically allocate memory for storing socket descriptors if (pthread_create(&thread, NULL, handle_client, static_cast<void*>(client_socket_ptr)) != 0) { perror("pthread_create failed"); delete client_socket_ptr; // If thread creation fails, free memory close(new_socket); continue; } // Separate threads and allow them to run independently pthread_detach(thread); // To test for deadlocks, only the first two client connections are accepted if (client_id >= 3) { close(new_socket); // Close redundant connections continue; } client_id++; } } int main() { int port = 8080; start_server(port); return 0; }