hiredis icon indicating copy to clipboard operation
hiredis copied to clipboard

API: redisContextConnectUnix has bug.

Open CodeIsPower1 opened this issue 1 month ago • 0 comments

V1.2.0 ` int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) { #ifndef _WIN32 int blocking = (c->flags & REDIS_BLOCK); struct sockaddr_un *sa; long timeout_msec = -1;

if (redisCreateSocket(c,AF_UNIX) < 0)
    return REDIS_ERR;
if (redisSetBlocking(c,0) != REDIS_OK)
    return REDIS_ERR;

c->connection_type = REDIS_CONN_UNIX;
if (c->unix_sock.path != path) {
    hi_free(c->unix_sock.path);

    c->unix_sock.path = hi_strdup(path);
    if (c->unix_sock.path == NULL)
        goto oom;
}

if (timeout) {
    if (redisContextUpdateConnectTimeout(c, timeout) == REDIS_ERR)
        goto oom;
} else {
    hi_free(c->connect_timeout);
    c->connect_timeout = NULL;
}

if (redisContextTimeoutMsec(c,&timeout_msec) != REDIS_OK)
    return REDIS_ERR;

/* Don't leak sockaddr if we're reconnecting */
if (c->saddr) hi_free(c->saddr);

sa = (struct sockaddr_un*)(c->saddr = hi_malloc(sizeof(struct sockaddr_un)));
if (sa == NULL)
    goto oom;

c->addrlen = sizeof(struct sockaddr_un);
sa->sun_family = AF_UNIX;
strncpy(sa->sun_path, path, sizeof(sa->sun_path) - 1);
if (connect(c->fd, (struct sockaddr*)sa, sizeof(*sa)) == -1) {
    if (errno == EINPROGRESS && !blocking) {
        /* This is ok. */
    } else {
        if (redisContextWaitReady(c,timeout_msec) != REDIS_OK)
            return REDIS_ERR;
    }
}

/* Reset socket to be blocking after connect(2). */
if (blocking && redisSetBlocking(c,1) != REDIS_OK)
    return REDIS_ERR;

c->flags |= REDIS_CONNECTED;
return REDIS_OK;

#else /* We currently do not support Unix sockets for Windows. / / TODO(m): https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ / errno = EPROTONOSUPPORT; return REDIS_ERR; #endif / _WIN32 */ oom: __redisSetError(c, REDIS_ERR_OOM, "Out of memory"); return REDIS_ERR; } `

///////////////////////////////////////////(man connect )/////////////////////////////////////////////////////////// EAGAIN For nonblocking UNIX domain sockets, the socket is nonblocking, and the connection cannot be completed immediately. For other socket families, there are insufficient entries in the routing cache.

   EALREADY
          The socket is nonblocking and a previous connection attempt  has
          not yet been completed.

   EBADF  sockfd is not a valid open file descriptor.

   ECONNREFUSED
          A connect() on a stream socket found no one listening on the re‐
          mote address.

   EFAULT The socket structure  address  is  outside  the  user's  address
          space.

   EINPROGRESS
          The socket is nonblocking and the connection cannot be completed
          immediately.  (UNIX domain sockets failed with EAGAIN  instead.)
          It is possible to select(2) or poll(2) for completion by select‐
          ing the socket for writing.  After select(2) indicates writabil‐
          ity,  use  getsockopt(2)  to  read  the SO_ERROR option at level
          SOL_SOCKET to determine whether connect() completed successfully
          (SO_ERROR  is  zero)  or  unsuccessfully (SO_ERROR is one of the
          usual error codes listed here, explaining  the  reason  for  the
          failure).

///////////////////////////////////////////////////(conclusion)/////////////////////////////////////////////////////////////////// For unix socket ,connect with non-blocking will return EAGAIN,not EINPROGRESS

CodeIsPower1 avatar May 27 '24 03:05 CodeIsPower1