Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When pub/sub establishes a link, the memory on the bind side grows #4352

Closed
CChyyyyyy opened this issue Feb 23, 2022 · 9 comments
Closed

When pub/sub establishes a link, the memory on the bind side grows #4352

CChyyyyyy opened this issue Feb 23, 2022 · 9 comments

Comments

@CChyyyyyy
Copy link

CChyyyyyy commented Feb 23, 2022

Please use this template for reporting suspected bugs or requests for help.

Issue description

Hi, i have a question,i create a sub that bind("tcp://127.0.0.1:3475") ,a pub that connect("tcp://127.0.0.1:3475"), and I keep sub running, and pub connects to it frequently .Every time pub connects to sub, sub will create a session_base_t, causing memory to grow until unbind is called to release resources .Is this unreasonable? Should session_baset_t be released every time pub and sub are disconnected?

Environment

All platforms

  • libzmq version (commit hash if unreleased): 4.3.4
  • OS: linux

Minimal test code / Steps to reproduce the issue

  1. create sub: zmq_bind(socket_, "tcp://127.0.0.1:3475");
  2. create pub: zmq_connect(socket_, "tcp://127.0.0.1:3475");
  3. keep sub runing, and pub connects to it frequently .

What's the actual result? (include assertion message & call stack if applicable)

Every time pub connects to sub, the memory will increase. I find the reason:Every time pub connects to sub, sub will create a session_base_t, but it doesn't release , when pub disconnects. All session_base_t are not destroyed until unbind is called.

stack information :
==30014== 82,000 bytes in 5 blocks are still reachable in loss record 45 of 45
==30014== at 0x48451EC: malloc (vg_replace_malloc.c:299)
==30014== by 0x43041F: zmq::pipepair(zmq::object_t, zmq::pipe_t, int const, bool const) (in /userdata/heyao.cai/zmq_ra
==30014== by 0x46D507: zmq::session_base_t::engine_ready() (in /userdata/heyao.cai/zmq_raw_pub)
==30014== by 0x4759AF: zmq::stream_engine_base_t::mechanism_ready() (in /userdata/heyao.cai/zmq_raw_pub)
==30014== by 0x475DDF: zmq::stream_engine_base_t::process_handshake_command(zmq::msg_t*) (in /userdata/heyao.cai/zmq_raw_pub
==30014== by 0x472813: zmq::stream_engine_base_t::in_event_internal() (in /userdata/heyao.cai/zmq_raw_pub)
==30014== by 0x4153D3: zmq::epoll_t::loop() (in /userdata/heyao.cai/zmq_raw_pub)
==30014== by 0x4405DF: thread_routine (in /userdata/heyao.cai/zmq_raw_pub)
==30014== by 0x48678E3: ??? (in /lib/libpthread-2.28.so)

What's the expected result?

When pub and sub are disconnected, release session_base_t on the bind side

@orangewsc
Copy link

You use API:bind() in sub and connect() in pub? What is mean " pub connects to it frequently "? Whether the old socket closed during the last connect when the new connect is comming? If all old sockets keep connecting , every time connect(), accept() will produce a new socket ,malloc a new memory in bind side.

@CChyyyyyy
Copy link
Author

I use API:bind() in sub and connect() in pub. I keep sub runing, never close socket. And i create a pub to connect it, when pub is connected to sub, the memory of the sub will grow. But when the pub is disconnected, the memory on the sub side does not decrease. When I create pub many times, the memory on the sub side grows to a large value. every time connect,sub side will malloc a new memory, but when disconnected, should the sub release resources immediately?

@orangewsc
Copy link

It is depend on whether you close() the socket when disconnected in sub side. If no, cause socket handle memory leak.

@CChyyyyyy
Copy link
Author

I read the relevant code, find that when sub establishes a connection it will create a session_base_t for msg transfer, but when pub is disconnected , this session_base_t dosen't work, why not delete it immediately? thanks for your reply

@orangewsc
Copy link

I'm not sure, i guess since you do not call close() explicitly. maybe you can read source code about LINUX SOCKET API & ZMQ::zmq_close(), and learn more about TCP/IP

@CChyyyyyy
Copy link
Author

CChyyyyyy commented Feb 24, 2022

Thank you very much. I know that these resources will be released when call close(). But I can't close the socket, because in the actual application, there are multiple pubs connected to this sub, I can't close the sub because one pub is disconnected.
Can we do this: 1. When a pub is disconnected, delete this session_base_t on the sub side immediately? 2. Or reuse the same session_base_t when the same ip:port connects again?

Relevant code to create session_base_t:
`
void zmq::tcp_listener_t::in_event ()
{
const fd_t fd = accept ();

//  If connection was reset by the peer in the meantime, just ignore it.
//  TODO: Handle specific errors like ENFILE/EMFILE etc.
if (fd == retired_fd) {
    _socket->event_accept_failed (
      make_unconnected_bind_endpoint_pair (_endpoint), zmq_errno ());
    return;
}

int rc = tune_tcp_socket (fd);
rc = rc
     | tune_tcp_keepalives (
       fd, options.tcp_keepalive, options.tcp_keepalive_cnt,
       options.tcp_keepalive_idle, options.tcp_keepalive_intvl);
rc = rc | tune_tcp_maxrt (fd, options.tcp_maxrt);
if (rc != 0) {
    _socket->event_accept_failed (
      make_unconnected_bind_endpoint_pair (_endpoint), zmq_errno ());
    return;
}

//  Create the engine object for this connection.
create_engine (fd);

}
`

@orangewsc
Copy link

That's a good question,i can not help you for this, maybe wait for author's reply

@bill-torpey
Copy link
Contributor

You may want to take a look at this issue, which sounds similar to yours: on Aug 23, 2018

The short version is that process_commands needs to run on the PUB socket in order to clean up resources. This is often done by calling the zmq_poll function on the ZMQ socket.

Please reply back and let us know if this information is helpful, and good luck.

@CChyyyyyy
Copy link
Author

Yes, this method can solve the problem. When the sub monitors the disconnection event, I call zmq_getsockopt (ZMQ_EVENTS) (this function will call process_commands), and the memory will not grow. Thanks a lot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants