Dan*_*ski 8 c c++ linux openssl signals
套接字函数喜欢send和receive可以通过信号中断.因此,需要一些额外的代码,例如检查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)
作为一个库,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。)