diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2016-10-24 08:40:46 -0700 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2016-10-24 08:41:55 -0700 |
commit | 5eb5a8dea64cad10634930a49e82148a6265e472 (patch) | |
tree | 85ce03ae6e8d8f016969605559968bd989beba5a | |
parent | a65a32aed450add3f81ecbdf9e07c44c97c5a14e (diff) | |
download | mu-5eb5a8dea64cad10634930a49e82148a6265e472.tar.gz |
3581
Fix CI. 3 different memory leaks in the socket internals. The hard one was recognizing the need for `receive-from-client-socket-and-close`.
-rw-r--r-- | 091socket.cc | 23 | ||||
-rw-r--r-- | 092socket.mu | 17 |
2 files changed, 37 insertions, 3 deletions
diff --git a/091socket.cc b/091socket.cc index ee76d3c6..180f2b27 100644 --- a/091socket.cc +++ b/091socket.cc @@ -50,6 +50,7 @@ case _OPEN_CLIENT_SOCKET: { break; } long long int result = reinterpret_cast<long long int>(client); +//? cerr << "$open-client-socket: " << client->fd << " -> " << result << '\n'; products.at(0).push_back(static_cast<double>(result)); break; } @@ -108,6 +109,7 @@ case _OPEN_SERVER_SOCKET: { break; } long long int result = reinterpret_cast<long long int>(server); +//? cerr << "$open-server-socket: " << server->fd << " -> " << result << '\n'; products.at(0).push_back(static_cast<double>(result)); break; } @@ -168,9 +170,11 @@ case _ACCEPT: { if (server) { socket_t* session = accept_session(server); long long int result = reinterpret_cast<long long int>(session); +//? cerr << "$accept from " << server->fd << ": " << session->fd << " -> " << result << '\n'; products.at(0).push_back(static_cast<double>(result)); } else { +//? cerr << "error in $accept from " << server->fd << '\n'; products.at(0).push_back(0); } break; @@ -230,6 +234,7 @@ case _READ_FROM_SOCKET: { products.resize(4); long long int x = static_cast<long long int>(ingredients.at(0).at(0)); socket_t* socket = reinterpret_cast<socket_t*>(x); +//? cerr << "$read-from-socket: polling " << socket->fd << '\n'; // 1. we'd like to simply read() from the socket // however read() on a socket never returns EOF, so we wouldn't know when to stop // 2. recv() can signal EOF, but it also signals "no data yet" in the beginning @@ -243,6 +248,7 @@ case _READ_FROM_SOCKET: { p.events = POLLIN | POLLHUP; int status = poll(&p, /*num pollfds*/1, /*timeout*/100/*ms*/); if (status == 0) { +//? cerr << "$read-from-socket: poll() timeout\n"; products.at(0).push_back(/*no data*/0); products.at(1).push_back(/*found*/false); products.at(2).push_back(/*eof*/false); @@ -260,15 +266,24 @@ case _READ_FROM_SOCKET: { } socket->polled = true; } +//? cerr << "reading from socket " << socket->fd << '\n'; int bytes = static_cast<int>(ingredients.at(1).at(0)); char* contents = new char[bytes]; bzero(contents, bytes); + int error_code = 0; int bytes_read = recv(socket->fd, contents, bytes-/*terminal null*/1, MSG_DONTWAIT); + if (bytes_read < 0) error_code = errno; +//? cerr << "bytes read: " << bytes_read << '\n'; +//? if (error_code) { +//? ostringstream out; +//? out << "error in $read-from-socket " << socket->fd; +//? perror(out.str().c_str()); +//? } products.at(0).push_back(new_mu_text(contents)); products.at(1).push_back(/*found*/true); products.at(2).push_back(/*eof*/bytes_read <= 0); - products.at(3).push_back(/*error*/0); - delete contents; + products.at(3).push_back(error_code); + delete[] contents; break; } @@ -288,9 +303,11 @@ case _WRITE_TO_SOCKET: { case _WRITE_TO_SOCKET: { long long int x = static_cast<long long int>(ingredients.at(0).at(0)); socket_t* session = reinterpret_cast<socket_t*>(x); +//? cerr << "writing to socket " << session->fd << '\n'; // write just one character at a time to the session socket long long int y = static_cast<long long int>(ingredients.at(1).at(0)); char c = static_cast<char>(y); +//? cerr << " " << c << '\n'; if (write(session->fd, &c, 1) != 1) { raise << maybe(current_recipe_name()) << "failed to write to socket\n" << end(); exit(0); @@ -321,7 +338,9 @@ case _CLOSE_SOCKET: { case _CLOSE_SOCKET: { long long int x = static_cast<long long int>(ingredients.at(0).at(0)); socket_t* socket = reinterpret_cast<socket_t*>(x); +//? cerr << "closing " << socket->fd << '\n'; close(socket->fd); + delete socket; break; } diff --git a/092socket.mu b/092socket.mu index 9fa4e415..eacc501f 100644 --- a/092socket.mu +++ b/092socket.mu @@ -16,10 +16,13 @@ F - example-server-test: $open-server-socket failed] ] source:&:source:char <- start-reading-from-network 0/real-resources, [localhost/], port response:text <- drain source +#? $print [app: done draining], 10/newline 10:@:char/raw <- copy *response memory-should-contain [ 10:array:character <- [abc] ] +#? $print [app: closing server socket], 10/newline + $close-socket socket ] # helper just for this scenario def example-handler query:text -> response:text [ @@ -62,6 +65,7 @@ F - example-server-test: $accept failed] query:text <- drain contents response:text <- call request-handler, query write-to-socket session, response +#? $print [app: closing session socket], 10/newline $close-socket session ] @@ -86,7 +90,7 @@ def start-reading-from-network resources:&:resources, uri:text -> contents:&:sou req:text <- interpolate [GET _ HTTP/1.1], path request-socket socket, req contents:&:source:char, sink:&:sink:char <- new-channel 10000 - start-running receive-from-socket socket, sink + start-running receive-from-client-socket-and-close socket, sink ] def request-socket socket:num, s:text -> socket:num [ @@ -118,6 +122,7 @@ def receive-from-socket socket:num, sink:&:sink:char -> sink:&:sink:char [ done?:bool <- greater-or-equal i, bytes-read break-if done? c:char <- index *req, i # todo: unicode +#? $print [read ], c, 10/newline sink <- write sink, c i <- add i, 1 loop @@ -125,6 +130,15 @@ def receive-from-socket socket:num, sink:&:sink:char -> sink:&:sink:char [ loop-unless eof? } sink <- close sink +#? $print [read status: ] found? [ ] eof? [ ] error 10/newline +] + +def receive-from-client-socket-and-close socket:num, sink:&:sink:char -> sink:&:sink:char [ + local-scope + load-ingredients + sink <- receive-from-socket socket, sink +#? $print [app: closing socket after reading], 10/newline + $close-socket socket ] def write-to-socket socket:num, s:text [ @@ -135,6 +149,7 @@ def write-to-socket socket:num, s:text [ { done?:bool <- greater-or-equal i, len break-if done? +#? $print i, 10/newline c:char <- index *s, i $write-to-socket socket, c i <- add i, 1 |