hiredis c socket

时间:2012-04-06 08:41:14

标签: 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)";
}

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

在preNtDeletKey rediscommand错误!并且错误类型为1,字符串为中断系统调用

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

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

2 个答案:

答案 0 :(得分:6)

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

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

int redisBufferRead(redisContext *c)
int redisBufferWrite(redisContext *c, int *done)

在这些函数中,处理EAGAIN错误,但不处理与“Interrupted system call”消息对应的EINTR错误。

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

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

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

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

<强>更新

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

  • 通过调用redisConnectNonBlock或激活非阻塞模式时 redisConnectUnixNonBlock()

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

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

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

答案 1 :(得分:0)

没有任何线索,但快速搜索说(在Linux内核上)系统调用可以在没有任何错误时被中断,当发生这种情况时,典型的事情就是再次执行。我的猜测,因为这里没有任何内容,Redis数据库或代码的某些部分不处理这种情况。 http://www.win.tue.nl/~aeb/linux/lk/lk-4.html