feifeiiong edited a comment on issue #1096:
URL: https://github.com/apache/incubator-brpc/issues/1096#issuecomment-619385096


   感谢您的回复!第四点确实是如您所说。关于1,3点,有一些不同的看法:
   1. DoRead 的设计确实是读到0即代表约定遇到EOF,但是SSL_read为0时的处理并不完备,以下内容摘自man:
   The following return values can occur:
   
   >0
   The read operation was successful; the return value is the number of bytes 
actually read from the TLS/SSL connection.
   
   0
   
   The read operation was not successful. The reason may either be a clean 
shutdown due to a "close notify" alert sent by the peer (in which case the 
SSL_RECEIVED_SHUTDOWN flag in the ssl shutdown state is set (see 
ssl_shutdown(3), ssl_set_shutdown(3)). It is also possible, that the peer 
simply shut down the underlying transport and the shutdown is incomplete. Call 
SSL_get_error() with the return value ret to find out, whether an error 
occurred or the connection was shut down cleanly ( SSL_ERROR_ZERO_RETURN 
   
   SSL_get_error:
   SSL_ERROR_ZERO_RETURN
   The TLS/SSL connection has been closed.
   SSL_ERROR_SYSCALL
   Some I/O error occurred. The OpenSSL error queue may contain more 
information on the error. If the error queue is empty (i.e. ERR_get_error() 
returns 0), ret can be used to find out more about the error: If ret == 0, an 
EOF was observed that violates the protocol. If ret == -1, the underlying BIO 
reported an I/O error (for socket I/O on Unix systems, consult errno for 
details).
   
   在iobuf中是这样处理的:
   ```
   const int rc = SSL_read(ssl, _block->data + _block->size, read_len);
           *ssl_error = SSL_get_error(ssl, rc);
           if (rc > 0) {
               const IOBuf::BlockRef r = { (uint32_t)_block->size, 
(uint32_t)rc, _block };
               _push_back_ref(r);
               _block->size += rc;
               if (_block->full()) {
                   Block* const saved_next = _block->portal_next;
                   _block->dec_ref();  // _block may be deleted
                   _block = saved_next;
               }
               nr += rc;
           } else {
               if (rc < 0) {
                   if (*ssl_error == SSL_ERROR_WANT_READ
                       || (*ssl_error == SSL_ERROR_SYSCALL
                           && BIO_fd_non_fatal_error(errno) == 1)) {
                       // Non fatal error, tell caller to read again
                       *ssl_error = SSL_ERROR_WANT_READ;
                   } else {
                       // Other errors are fatal
                       return rc;
                   }
               }
               return (nr > 0 ? nr : rc);
   ```
   在rc == 0时,返回,并置错误码,此处的错误码,有可能是SSL_ERROR_SYSCALL/SSL_ERROR_ZERO_RETURN, 
在socket.cpp:
   
   int ssl_error = 0;
       ssize_t nr = _read_buf.append_from_SSL_channel(_ssl_session, &ssl_error, 
size_hint);
       switch (ssl_error) {
       case SSL_ERROR_NONE:  // `nr' > 0
           break;
               
       case SSL_ERROR_WANT_READ:
           // Regard this error as EAGAIN
           errno = EAGAIN;
           break;
               
       case SSL_ERROR_WANT_WRITE:
           // Disable renegotiation
           errno = EPROTO;
           return -1;
   
       default: {
           const unsigned long e = ERR_get_error();
           if (nr == 0) {
               // Socket EOF or SSL session EOF
           } else if (e != 0) {
               LOG(WARNING) << "Fail to read from ssl_fd=" << fd()
                            << ": " << SSLError(e);
               errno = ESSL;
           } else {
               // System error with corresponding errno set
               PLOG(WARNING) << "Fail to read from ssl_fd=" << fd();
           }
           break;
       }
   如上,以上错误码被default捕获,而此刻nr 有可能!=0 (iobuf.cpp : return (nr > 0 ? nr : rc);), 
从而导致该EOF被忽略,导致socket无法关闭。在实际应用中,该问题已经频繁被触发,打印日志类似:
    Fail to read from ssl_fd=id:Success
   DoWrite有类似的问题,这里就不贴代码了,烦请您看看!


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@brpc.apache.org
For additional commands, e-mail: dev-h...@brpc.apache.org

Reply via email to