libevent - does this c++ code have memory leaks? -
i'm trying understand libevent
c++ code got this page.
i'm bit confused - correct think code might have memory leaks?
it seems connectiondata
pointer created in on_connect()
callback, delete()
called on bad read or after write complete.
if connection accept()
ed - there no reads or writes? pointer stays in daemon memory?
#include <event.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <iostream> // read/write buffer max length static const size_t max_buf = 512; typedef struct { struct event ev; char buf[max_buf]; size_t offset; size_t size; } connectiondata; void on_connect(int fd, short event, void *arg); void client_read(int fd, short event, void *arg); void client_write(int fd, short event, void *arg); int main(int argc, char **argv) { // check arguments if (argc < 3) { std::cout << "run options: <ip address> <port>" << std::endl; return 1; } // create server socket int server_sock = socket(af_inet, sock_stream, 0); if (server_sock == -1) { std::cerr << "failed create socket" << std::endl; return 1; } sockaddr_in sa; int on = 1; char * ip_addr = argv[1]; short port = atoi(argv[2]); sa.sin_family = af_inet; sa.sin_port = htons(port); sa.sin_addr.s_addr = inet_addr(ip_addr); // set option so_reuseaddr reuse same host:port in short time if (setsockopt(server_sock, sol_socket, so_reuseaddr, &on, sizeof(on)) == -1) { std::cerr << "failed set option so_reuseaddr" << std::endl; return 1; } // bind server socket ip:port if (bind(server_sock, reinterpret_cast<const sockaddr*>(&sa), sizeof(sa)) == -1) { std::cerr << "failed bind server socket" << std::endl; return 1; } // make server listen if (listen(server_sock, 10) == -1) { std::cerr << "failed make server listen" << std::endl; return 1; } // init events struct event evserver_sock; // initialize event_init(); // set connection callback (on_connect()) read event on server socket event_set(&evserver_sock, server_sock, ev_read, on_connect, &evserver_sock); // add server event without timeout event_add(&evserver_sock, null); // dispatch events event_dispatch(); return 0; } // handle new connection {{{ void on_connect(int fd, short event, void *arg) { sockaddr_in client_addr; socklen_t len = 0; // accept incoming connection int sock = accept(fd, reinterpret_cast<sockaddr*>(&client_addr), &len); if (sock < 1) { return; } // set read callback client socket connectiondata * data = new connectiondata; event_set(&data->ev, sock, ev_read, client_read, data); // reschedule server event event_add(reinterpret_cast<struct event*>(arg), null); // schedule client event event_add(&data->ev, null); } //}}} // handle client request {{{ void client_read(int fd, short event, void *arg) { connectiondata * data = reinterpret_cast<connectiondata*>(arg); if (!data) { close(fd); return; } int len = read(fd, data->buf, max_buf - 1); if (len < 1) { close(fd); delete data; return; } data->buf[len] = 0; data->size = len; data->offset = 0; // set write callback client socket event_set(&data->ev, fd, ev_write, client_write, data); // schedule client event event_add(&data->ev, null); } //}}} // handle client responce {{{ void client_write(int fd, short event, void *arg) { connectiondata * data = reinterpret_cast<connectiondata*>(arg); if (!data) { close(fd); return; } // send data client int len = write(fd, data->buf + data->offset, data->size - data->offset); if (len < data->size - data->offset) { // failed send rest data, need reschedule data->offset += len; event_set(&data->ev, fd, ev_write, client_write, data); // schedule client event event_add(&data->ev, null); } close(fd); delete data; } //}}}
the documentation event_set says valid event types ev_read
or ev_write
, callback invoked ev_timeout
, ev_signal
, ev_read
, or ev_write
. documentation not clear, expect read callback invoked when socket closed client. expect delete
in failure branch in client_read
handle situation.
note that case if client sends fin
or rst
packet. client establish connection , leave open forever. reason, code should modified have timeout (perhaps via event_once) , require client send message within timeout.
Comments
Post a Comment