OpenSSL和信号

Dan*_*ski 8 c c++ linux openssl signals

套接字函数喜欢sendreceive可以通过信号中断.因此,需要一些额外的代码,例如检查errno == EINTR.这在相应的手册页上进行了描述.

我不知道,当OpenSSL的功能使用,例如这是如何工作的SSL_write,SSL_read.他们的手册没有说明信号.我也尝试谷歌这个,但没有运气.你知道OpenSSL是否在内部处理信号,还是需要一些额外的代码?如果是,如何检查函数调用是否被信号中断?

更新:

看起来OpenSSL不处理重试.它只在BIO对象上设置"should retry"标志.所以我需要使用这样的东西来检测呼叫是否被中断并且需要重试:

int result = SSL_write(ssl, buff, length);
if ((result < 0) && BIO_should_retry(SSL_get_wbio(ssl)))
    // need to retry

int result = SSL_read(ssl, buff, length);
if ((result < 0) && BIO_should_retry(SSL_get_rbio(ssl)))
    // need to retry
Run Code Online (Sandbox Code Playgroud)

alk*_*alk 4

作为一个库,OpenSSL 无法对使用它的特定程序如何处理信号做出任何假设。因此它需要处理系统调用在接收到信号时被中断的情况。

检查重试失败是否有意义read()是在 OpenSSL 内部实现的。

BIO_should_retry()如果BIO_read()(或)失败则使用BIO_write()

有关示例,请阅读此处:http://cvs.openssl.org/rlog ?f=openssl/demos/bio/sconnect.c

实现的相关代码如下:

static int sock_read(BIO *b, char *out, int outl)
    {
    int ret=0;

    if (out != NULL)
            {
            clear_socket_error();
            ret=readsocket(b->num,out,outl);
            BIO_clear_retry_flags(b);
            if (ret <= 0)
                    {
                    if (BIO_sock_should_retry(ret))
                            BIO_set_retry_read(b);
                    }
            }
    return(ret);
    }
Run Code Online (Sandbox Code Playgroud)

相关的参考函数在这里:

(在大多数 IXish 平台上get_last_socket_error()返回)errno

int BIO_sock_should_retry(int i)
    {
    int err;

    if ((i == 0) || (i == -1))
            {
            err=get_last_socket_error();

#if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */
            if ((i == -1) && (err == 0))
                    return(1);
#endif

            return(BIO_sock_non_fatal_error(err));
            }
    return(0);
    }


int BIO_sock_non_fatal_error(int err)
        {
        switch (err)
                {
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_NETWARE)
# if defined(WSAEWOULDBLOCK)
        case WSAEWOULDBLOCK:
# endif

# if 0 /* This appears to always be an error */
#  if defined(WSAENOTCONN)
        case WSAENOTCONN:
#  endif
# endif
#endif

#ifdef EWOULDBLOCK
# ifdef WSAEWOULDBLOCK
#  if WSAEWOULDBLOCK != EWOULDBLOCK
        case EWOULDBLOCK:
#  endif
# else
        case EWOULDBLOCK:
# endif
#endif

#if defined(ENOTCONN)
        case ENOTCONN:
#endif

#ifdef EINTR
        case EINTR:
#endif

#ifdef EAGAIN
# if EWOULDBLOCK != EAGAIN
        case EAGAIN:
# endif
#endif

#ifdef EPROTO
        case EPROTO:
#endif

#ifdef EINPROGRESS
        case EINPROGRESS:
#endif

#ifdef EALREADY
        case EALREADY:
#endif
                return(1);
                /* break; */
        default:
                break;
                }
        return(0);
        }
Run Code Online (Sandbox Code Playgroud)

详细信息sock_read()请参阅此处检查:http://cvs.openssl.org/rlog ?f=openssl/crypto/bio/bss_sock.c

(引用的来源以及所使用的缩进来自版本 1.0.1e。)