You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用jsonrpc-c服务器fork子进程时如何让客户端正常退出?

问题描述

我正在使用jsonrpc-c开发一个远程shell玩具。客户端通过nc向服务器发送请求,命令如下:

echo "{\"method\":\"sayHello\"}" | nc localhost 1234

服务器代码示例如下:

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <signal.h> 
#include "jsonrpc-c.h"
#define DEFAULT_PORT            1234  //the port users will be connecting to

static struct jrpc_server my_server;


cJSON * hello(jrpc_context * ctx, cJSON * params, cJSON *id) {
  pid_t pid = fork();
  if (pid==0)
  {
    freopen( "/dev/null", "w", stdout );
    freopen( "/dev/null", "r", stdin ); 
    signal(SIGCHLD,SIG_IGN);
    while(true){
    printf("hello in child\n");
    }
    exit(1);
  }
  printf("hello in father\n");
    return cJSON_CreateString("done");
}

void main(int argc, char **argv)
{
    int port;
    if (argc == 2) 
        port = atoi(argv[1]);
    else 
        port = DEFAULT_PORT;

    jrpc_server_init(&my_server, (int)port);

    jrpc_register_procedure(&my_server, hello, "sayHello", NULL);

    jrpc_server_run(&my_server);
    jrpc_server_destroy(&my_server);
}

执行上述客户端命令时,客户端会永久阻塞。请问如何实现服务器父进程返回响应后客户端正常退出,同时让服务器子进程持续运行?

问题原因与解决方法

原因分析

客户端nc阻塞的核心原因是:子进程继承了父进程的客户端连接套接字,导致这个套接字的引用计数不为0,服务器父进程返回响应后并没有真正关闭连接,nc一直等待连接关闭信号,所以永久阻塞。

解决步骤

要解决这个问题,需要在子进程中主动关闭继承的套接字,同时调整信号处理逻辑的位置。具体修改如下:

  1. 获取当前连接的套接字:jsonrpc-c的jrpc_context结构体中包含了客户端连接的文件描述符(通常为ctx->conn_fd,若字段名称不同,替换为库中对应字段即可)。
  2. 子进程中关闭套接字:在子进程代码块中添加关闭该套接字的操作,释放连接引用。
  3. 调整信号处理位置:将signal(SIGCHLD,SIG_IGN)移到父进程中,避免子进程修改父进程的信号处理规则。

修改后的hello函数代码:

cJSON * hello(jrpc_context * ctx, cJSON * params, cJSON *id) {
  pid_t pid = fork();
  if (pid == 0)
  {
    // 关闭继承的客户端连接套接字,释放连接引用
    close(ctx->conn_fd);

    freopen( "/dev/null", "w", stdout );
    freopen( "/dev/null", "r", stdin ); 
    
    while(true){
      printf("hello in child\n");
      sleep(1); // 避免子进程无限制循环占用CPU
    }
    exit(EXIT_FAILURE);
  }
  // 父进程忽略子进程退出信号,防止产生僵尸进程
  signal(SIGCHLD, SIG_IGN);
  printf("hello in father\n");
  return cJSON_CreateString("done");
}

额外优化说明

  • 子进程中的printf已被重定向到/dev/null,添加sleep(1)可以避免子进程持续占用CPU资源。
  • 若ctx->conn_fd不是正确的连接描述符字段,可查看jsonrpc-c的头文件,找到对应表示客户端套接字的成员。

内容的提问来源于stack exchange,提问作者plznobug

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 08:23:34