2014-06-12 69 views
7

插座功能如sendreceive可以被信號中斷。由於這個需要一些額外的代碼,例如檢查errno == EINTR。這在相應的手冊頁中描述。OpenSSL和信號

我不知道在使用OpenSSL函數時這是如何工作的,例如, SSL_writeSSL_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 

回答

3

爲一個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()回報errno上最IXish平臺)

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://cvs.openssl.org/rlog?f=openssl/crypto/bio/bss_sock.c

(該所使用的凹痕是從版本1.0.1e沿着引述消息人士。)