nats-io / nats.rs

Rust client for NATS, the cloud native messaging system.
Apache License 2.0
991 stars 158 forks source link

crash app when disconnect after timeout #863

Closed guzuomuse closed 1 year ago

guzuomuse commented 1 year ago

Make sure that these boxes are checked before submitting your issue -- thank you!

NATS version (grep 'name = "nats"' Cargo.lock -A 1)

nats --version 0.0.34 nats.rs version :0.24.0

rustc version (rustc --version - we support Rust 1.41 and up)

rustc --version rustc 1.67.0 (fc594f156 2023-01-24)

OS/Container environment:

Windows10

Steps or code to reproduce the issue:

let me explain how to reproduce.

i want to build a dll libray using this crate for communicating with Metatrade5(a well known trading software.let's call it mt5 for short) so first we create a dll using rust.

use std::slice;

#[no_mangle]

pub extern "C" fn create_nats_conn(address: *mut u16) -> *mut nats::Connection {
    let address = convert_u16_to_string(address);
    let conn = nats::connect(address).unwrap();
    Box::into_raw(Box::new(conn))
}

fn convert_u16_to_string(str_u16: *mut u16) -> String {
    assert!(!str_u16.is_null());

    let mut i = 0;
    let string_u8 = unsafe {
        while *str_u16.add(i) != 0 {
            i += 1;
        }
        let str_u16_slice = slice::from_raw_parts(str_u16, i);
        String::from_utf16(str_u16_slice).unwrap()
    };
    string_u8
}

the code above do nothing just export a create_nats_conn function which take a *mut u16 parameter because the mt5 using string in u16 format. next,let 's call the dll in mt5 script a named mql5 language for mt5. bellow is the script code:

//+------------------------------------------------------------------+

//|                                                   nats_issue.mq5 |

//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
#import "E:\www\rust_projects\rust_ffi_projects\dll_mt5\target\release\dll_mt5.dll"// make sure the imported dll path is correct 
void create_nats_conn(string address);
#import
void OnStart()
  {
  create_nats_conn("nats://localhost:4222");
  Sleep(5000);//wait for some seconds in order to see `nats-top` whether we have connection established
  // after 5 second ,though the thread of this script is closed. but we still can see the connection listed the `nats-top`. cuase.the connection will keep about 2 minutes.
  }
//+------------------------------------------------------------------+

run the script and then we can use the nats-top command from windows cmd. we can see we have conn created by rust.

after 5 seconds the script closed. as described in the mql5 script: we still can see the connection listed the nats-top. cuase.the connection will keep about 2 minutes. and wait for about 2 minutes the mt5 software crashed!!!!!!!

Expected result:

expected result is : we can close the connection manually by create a dll exported function using Box::from_raw(...) and even connection closed implicitly after 2 minutes . it should'nt crash the mt5 software.

Actual result:

connection closed and crash the mt5 software.

by a mention : i think the reason why the connection still keep abount 2mints is that ,we have this code in this crate:

// const PING_INTERVAL: Duration = Duration::from_secs(2 * 60); which located in src/client.rs

guzuomuse commented 1 year ago

i can confirm it not a windows issue yet not a rust issue, it is a 'crate' issue.

why?

let me create a nats connection from scratch:

rust code:

use std::net::TcpStream;

use std::slice;

pub extern "C" fn create_nats_conn_with_tcpstream(address: *mut u16) -> *mut TcpStream {
    let address = convert_u16_to_string(address);// address->:tcp://localhost:4222
    let tcp_stream = TcpStream::connect(address).unwrap();
    Box::into_raw(Box::new(tcp_stream))
}
// pub extern "C" fn close_tcp_conn(tcp_stream:*mut TcpStream){
//     unsafe{
//       let _=Box::from_raw(tcp_stream);  
//     };
// }

this code works fine .we can see the conn established with 'nats-top'. even this connection is closed. it will not crash the mt5 software.

but if you want to publish the message ..subscribe message we must do everything from scratch.that's say we can not use this crate.we must create a new crate like the nats.rs does.