【问题标题】:How "kill" a Pthread?如何“杀死”一个 Pthread?
【发布时间】:2012-08-15 06:47:06
【问题描述】:

我正在学习 Pthreads,并且想知道杀死这样一个对象的最佳方法是什么。在寻找类似问题后,我无法找到“明确”的答案,但请随时向我指出任何相关问题。

我正在使用一个小型客户端服务器应用程序,其中服务器主线程正在侦听客户端连接的套接字。每次客户端连接时,服务器都会在 while true 循环中创建一个执行“无限工作”的新线程。现在我想在同一个客户端在套接字上发送“停止”请求时停止这个循环。

如果知道客户端是通过每个套接字消息中提供的 ID 来识别的,您将如何实现这样的行为?使用共享变量(在主服务器线程和客户端服务器线程之间)作为 while 循环中的测试条件。使用 PThread 函数?

【问题讨论】:

  • 当线程从socket读取“停止”请求时,仅仅退出该线程的函数还不够吗?
  • 套接字由服务器的主线程读取,而不是服务器“客户端”线程...
  • 有趣的设置...所以每个客户端都有一个线程,但您没有线程自己读取?你这样做有理由吗?在我看来,这只会让你的生活更加艰难。
  • @LnxPrgr3:完全同意你的看法

标签: c sockets pthreads client-server


【解决方案1】:

没有办法强行杀死单个 POSIX 线程;这是故意的,设计使然。相反,如果您的线程需要被其他线程停止,您应该设计在其中运行的代码以考虑到这一点。执行此操作的惯用方法是使用退出标志变量(受互斥体保护)和条件变量。

还有pthread_cancel,可以用来请求线程退出。正确使用它需要使用pthread_cleanup_push 设置清理处理程序和/或使用pthread_setcancelstate 暂时禁用取消。

【讨论】:

    【解决方案2】:

    你可以这样设计你的服务器:

    typedef struct _client_data_buffer
    {
       char user_cmd[16];    /* Could be "CONTINUE" or "STOP" */
       char* buffer;         /* Client network data. You can use a fixed size buffer for this part also */
    } client_data_buffer;
    
    /* client encode data before sending to the server */
    size_t encode_client_data(client_data_buffer* data_buf, char* buf)
    {
        size_t serialized_bytes = 0;    /* Can help for transmission errors checking */
    
        /* Serialize the cmd */
        memcpy(buf + serialized_bytes, data_buf->user_cmd, strlen(data_buf->user_cmd) + 1);
        serialized_bytes += strlen(data_buf->user_cmd) + 1;
        /* Serialize the data the client want to send to the server */
        memcpy(buf + serialized_bytes, data_buf->buffer, strlen(data_buf->buffer) + 1);
        serialized_bytes += strlen(arch->nombre_arch) + 1;
    
        return serialized_bytes;
    }
    
    /* Server decode client data */
    void decode_client_data(char* buf, client_data_buffer* data_buf)
    {
        /* Your decode here */
    }
    
    int create_server(int port, char *address)
    {
        /* Create you server */
    }
    
    void* thread_callback(void *client_data)
    {
        /* client socket descriptor */
        int client_id = *(int *) client_data;
        client_data_buffer *some_user_data;
        char some_buffer[BUFFER_SIZE];
    
        /* receiving data until STOP command is received */
    
        while(1)
        {
            /* receive */
            recv(client_id, some_buffer, BUFFER_SIZE, 0);
    
            /* decode some_buffer to some_user_data */
    
            /* compare */
            if (strcmp("STOP", some_user_data->user_cmd) == 0)
            {
                /* shutdown and close client socket and exit */
            }
    
            else
            {
                /* Parse incoming data and do the job */
            }
        }
    
        return NULL;
    }
    
    int main(int argc, char **argv) {
        int server_socket;
        int client_socket;
        int result;
    
        /* Crete our server */
        server_socket = create_tcp_server (my_port_number, my_address);
    
        while (1) {
            pthread_t thread_id;
    
            client_socket = accept(server_socket, NULL ,NULL);
            result = pthread_create(&thread_id, NULL, thread_callback, (void *) client_socket);
            if (result != 0) 
            {
              /* Handle errors with errno and exit */
            }
            /* We don't care about the return status ---> avoid zombies and handling threads termination */
            pthread_detach(thread_id);
        }
    
        exit (EXIT_SUCCESS);
    }
    

    【讨论】:

      【解决方案3】:

      您不应该强制线程退出。 您应该设计您的程序,以便在发送“停止”时存在 while 循环。

      类似:

        while(strcmp(word, "stop")!=0){
              word = read_word_from_socket();
              ......
        }
      

      【讨论】:

      • 但是我有一个用于所有线程的套接字,现在套接字读取是在主服务器线程中完成的......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-24
      • 2011-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-13
      • 2014-10-03
      相关资源
      最近更新 更多