像send
和receive
这样的套接字函数可以被信号中断。 由于这一些额外的代码是必要的,例如检查errno == EINTR
。 这在相应的手册页中描述。
我想知道如何使用OpenSSL函数,如SSL_write
, SSL_read
。 他们的手册没有提到任何有关信号的事情。 我也试图谷歌这一点,但没有运气。 你知道OpenSSL是否在内部处理信号,还是需要一些额外的代码? 如果是,如何检查函数调用是否被信号中断?
更新:
看来,OpenSSL不处理重试。 它只在BIO对象上设置“应该重试”标志。 所以我需要使用这样的东西来检测是否呼叫中断,并需要重试:
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
作为一个libray,OpenSSL不能对使用它的特定程序如何处理信号做出任何假设。 所以在接收信号时需要处理系统调用被中断的情况。
检查是否有意义重试失败的read()
是在OpenSSL内部实现的。
如果BIO_read()
(或BIO_write()
)失败,请使用BIO_should_retry()
。
阅读这里的例子: 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); }
相关的功能在这里:
( get_last_socket_error()
在大多数IXish平台上返回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); }
有关详细信息,请参阅sock_read()
以进行检查: http : sock_read()
(引用的引用来源于版本1.0.1e。)