about summary refs log tree commit diff stats
path: root/091socket.cc
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2016-10-24 08:40:46 -0700
committerKartik K. Agaram <vc@akkartik.com>2016-10-24 08:41:55 -0700
commit5eb5a8dea64cad10634930a49e82148a6265e472 (patch)
tree85ce03ae6e8d8f016969605559968bd989beba5a /091socket.cc
parenta65a32aed450add3f81ecbdf9e07c44c97c5a14e (diff)
downloadmu-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`.
Diffstat (limited to '091socket.cc')
-rw-r--r--091socket.cc23
1 files changed, 21 insertions, 2 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;
 }