hiredis c socket

jia*_*amo 2 c redis

reply = redisCommand(rcontext,"HGET %u %u",env->cr[3] ,KeyHandle);
if(reply == NULL)
{
printf("in preNtDeletKey rediscommand error ! and the err type is %d the string is %s \n" ,rcontext->err,rcontext->errstr)";
}
Run Code Online (Sandbox Code Playgroud)

这里我得到一个错误,回复返回NULL输出

在preNtDeletKey rediscommand错误!并且err类型为1,字符串是Interrupted system call

我在我的项目中使用它.而且我在hiredis源中找不到中断系统调用我想知道导致系统调用中断的原因是什么hiredis将字符串写入redisContext(因为我在sourec中找不到)

我们如何避免中断系统调用?

Did*_*zia 6

hiredis软件包使用Redis协议封送您的命令,并将其发送到Redis服务器.然后它同步等待回复.

您将在hiredis.c文件中找到处理套接字的函数:

int redisBufferRead(redisContext *c)
int redisBufferWrite(redisContext *c, int *done)
Run Code Online (Sandbox Code Playgroud)

在这些函数中,处理EAGAIN错误,但不处理与"中断系统调用"消息对应的EINTR错误.

结果是任何Unix信号,当hiredis正在执行写操作时(或者更可能)执行读操作时,该进程会接收该信号,可能会中断操作并导致此错误.

您首先需要了解应用程序接收哪种信号.根据信号和应用程序的性质,有多种方法可以处理这种情况:

  • 在进行Redis调用之前屏蔽或推迟信号处理程序
  • 将信号绑定到事件循环处理程序(如果有)以避免在不期望的情况下处理信号
  • 专用一个给定的线程来处理所有信号(并避免在这个线程中的任何Redis调用)
  • 使用SA_RESTART选项(在sigaction中)告诉系统自动重放被中断的系统调用
  • 只是尝试再次进行操作(尽管可能不可能)

就个人而言,我倾向于hiredis以更优雅的方式处理这种情况(即像EAGAIN一样处理EINTR).

更新:

通常在两种情况下返回EAGAIN错误:

  • 当非阻断模式已经通过调用redisConnectNonBlock或redisConnectUnixNonBlock激活()

  • 当连接处于阻塞模式(默认)并且已调用redisSetTimeout()方法来设置超时时

请注意,在客户端调用redisSetTimeout()函数只需设置套接字的SO_RCVTIMEO和SO_SNDTIMEO 属性.它与Redis配置文件中定义的超时完全无关,Redis配置文件是服务器端空闲超时(如果连接处于非活动状态超过N秒,则Redis服务器能够关闭连接).

在第二种情况下获取EAGAIN意味着Redis实例对提供的超时响应不够.您可能只想简单地增加超时或进一步调查Redis服务器端的延迟问题.