packages feed

ghc-debug-stub 0.2.1.0 → 0.3.0.0

raw patch · 5 files changed

+78/−50 lines, 5 filesdep ~ghc-debug-conventionPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: ghc-debug-convention

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,10 @@ # Revision history for ghc-debug-stub +## 0.3.0.0 -- 2022-10-06++* Allow clients to reconnect multiple times to debuggee (Finley McIlwaine)+* Fix initialisation bugs due to uninitialised len (Teo Camarasu)+ ## 0.2.1.0 -- 2022-05-06  * Fix bug with write_block on BF_COMPACT closures
cbits/socket.cpp view
@@ -8,15 +8,21 @@ Socket::Socket(int fd)   : fd(fd) { } -void Socket::read(char *buf, size_t len) {+size_t Socket::read(char *buf, size_t len) {+    int n_read = 0;     while (len > 0) {         ssize_t ret = ::read(this->fd, (void *) buf, len);         if (ret < 0) {             throw SocketError(errno, "read");+        } else if (ret == 0) {+            // if read() returns 0 it should be considered a disconnect+            return 0;         }         len -= ret;         buf += ret;+        n_read += ret;     }+    return n_read; }  void Socket::write(const char *buf, size_t len) {
cbits/socket.h view
@@ -17,6 +17,6 @@   public:     Socket(int fd);     /* read len bytes into the given buffer */-    void read(char *buf, size_t len);+    size_t read(char *buf, size_t len);     void write(const char *buf, size_t len); };
cbits/stub.cpp view
@@ -104,25 +104,26 @@     void flush(response_code status) {         if (status != RESP_OKAY_CONTINUES || this->tail != this->buf + sizeof(Header)) {             size_t len = this->tail - this->buf;-            trace("LEN: %lu", len);+            trace("bytes in response payload: %lu\n", len);             uint32_t len_payload;             uint16_t status_payload;             len_payload=htonl(len);             status_payload = htons(status);-            trace("STATUS: %d\n", status);+            trace("responding with status: %d\n", status);             // Header is the length             this->sock.write((char *) &len_payload, sizeof(uint32_t));             // Then status             this->sock.write((char *) &status_payload, sizeof(uint16_t));             // then the body, usually empty-    trace("FLUSHING(%lu)( ", len);-    for (int i = 0; i < len; i++)-    {-      trace("%02X", buf[i]);-    }-    trace("\n");+            trace("responding with body of length %lu: ( ", len);+            for (int i = 0; i < len; i++)+            {+                trace("%02X", buf[i]);+            }+            trace(" )\n");             this->sock.write(this->buf, len);             this->tail = this->buf;+            trace("response written to socket\n\n");         }     } @@ -175,7 +176,7 @@     }      void finish(enum response_code status) {-        trace("FINISH: %d\n", status);+        trace("finishing with code: %d\n", status);         this->flush(status);     } @@ -191,6 +192,7 @@  extern "C" void pause_mutator() {+  trace("pausing mutator\n");   pid_t pid;   if (use_fork){     pid = fork();@@ -214,11 +216,13 @@  extern "C" void resume_mutator() {-  //trace("Resuming %p %p\n", r_paused.pausing_task, r_paused.capabilities);+  trace("resuming mutator\n");   if (use_fork){+    trace("exiting child\n");     // Exit, the parent is blocked until we are finished.     exit(0);   } else {+    trace("resuming rts\n");     rts_resume(r_paused);     paused = false;   }@@ -260,7 +264,7 @@     uint32_t b = 0;     uint32_t size_payload;     size_payload=htonl(size);-    trace("SIZE %lu", size);+    trace("SIZE %llu", size);     resp.write((uint32_t) size_payload);      for (uint32_t i = 0; i < size; b++) {@@ -280,7 +284,7 @@     // Small bitmap     uint32_t size_payload;     size_payload=htonl(size);-    trace("SIZE %lu", size);+    trace("SIZE %llu", size);     resp.write((uint32_t) size_payload);     while (size > 0) {         resp.write((uint8_t) ! (bitmap & 1));@@ -361,34 +365,38 @@  /* return non-zero on error */ static int handle_command(Socket& sock, const char *buf, uint32_t cmd_len) {-    trace("HANDLE: %d\n", cmd_len);+    trace("handling command of length: %d\n", cmd_len);     Parser p(buf, cmd_len);     Response resp(sock);-    trace("P %lu\n", p.available());     uint32_t cmd = ntohl(p.get<uint32_t>());-    trace("CMD: %d\n", cmd);+    trace("read CommandId: %d\n", cmd);     switch (cmd) {       case CMD_VERSION:         uint32_t ver_payload;-        ver_payload=htonl(0);+        uint32_t ver_payload1;+        ver_payload=htonl(__GLASGOW_HASKELL__) ;+        ver_payload1=htonl(__GLASGOW_HASKELL_PATCHLEVEL1__) ;         resp.write(ver_payload);+        resp.write(ver_payload1);         resp.finish(RESP_OKAY);         break;        case CMD_PAUSE:+        trace("handling pause command\n");+        trace("paused already?: %s\n", paused ? "yes" : "no");         use_fork = (bool)ntohl(p.get<uint8_t>());-        trace("PAUSE: %d", paused);-        trace("PAUSE(FORK): %d", use_fork);         if (paused) {-            trace("ALREADY");             resp.finish(RESP_ALREADY_PAUSED);         } else {+            trace("fork?: %s\n", use_fork ? "yes" : "no");             pause_mutator();             resp.finish(RESP_OKAY);         }         break;        case CMD_RESUME:+        trace("handling resume command\n");+        trace("already running?: %s\n", paused ? "no" : "yes");         if (!paused) {             resp.finish(RESP_NOT_PAUSED);         } else if (r_poll_pause_resp){@@ -638,23 +646,29 @@     Socket sock(sock_fd);     char *buf = new char[MAX_CMD_SIZE];     while (true) {+        trace("handler is waiting for a request\n");         uint32_t cmdlen_n, cmdlen; -        sock.read((char *)&cmdlen_n, 4);-        cmdlen = ntohl(cmdlen_n);+        size_t n_read = sock.read((char *)&cmdlen_n, 4); +        // If the read returns 0, consider it a disconnect+        if (n_read == 0) {+            trace("handler is done\n");+            return;+        }+         cmdlen = ntohl(cmdlen_n);+         char *large_buf = buf;         bool use_large_buf = cmdlen > MAX_CMD_SIZE;         if (use_large_buf) {           large_buf = new char[cmdlen];         } -        trace("LEN: %d\n", cmdlen);+        trace("reading cmd of length: %d\n", cmdlen);         sock.read(large_buf, cmdlen);-        trace("CONT:%s\n", buf);+        trace("leftover: %s\n", buf);         try {-            trace("LEN2: %d\n", cmdlen);             handle_command(sock, large_buf, cmdlen);         } catch (Parser::EndOfInput e) {             barf("error");@@ -698,55 +712,58 @@  extern "C" void start(const char* socket_path) {-    trace("starting\n");+    trace("starting with socket path: %s\n", socket_path);     struct sockaddr_un local, remote;      if (strlen(socket_path) >= sizeof(local.sun_path)) {         barf("socket_path too long: \"%s\"", socket_path);     } -    int s = socket(AF_UNIX, SOCK_STREAM, 0);-    if (s == -1) {+    // Open the socket for listening+    int listenHdl = socket(AF_UNIX, SOCK_STREAM, 0);+    if (listenHdl == -1) {         barf("socket failed");     } -    // Bind socket-    {-        local.sun_family = AF_UNIX;-        strncpy(local.sun_path, socket_path, sizeof(local.sun_path));-        unlink(local.sun_path);-        if (bind(s, (struct sockaddr *) &local, sizeof(local)) != 0) {-            barf("bind failed");-        }+    // Bind the socket to an address+    local.sun_family = AF_UNIX;+    strncpy(local.sun_path, socket_path, sizeof(local.sun_path));+    unlink(local.sun_path);+    if (bind(listenHdl, (struct sockaddr *) &local, sizeof(local)) != 0) {+        barf("bind failed");     } -    if (listen(s, 1) != 0) {+    // Listen for connections+    if (listen(listenHdl, 1) != 0) {         barf("listen failed");     }     fflush(stdout);+     while (true) {-        socklen_t len;-        int s2 = accept(s, (struct sockaddr *) &remote, &len);-        if (s2 == -1) {-          barf("accept failed %d", s2);+        // Wait for client connection+        socklen_t len = sizeof(remote);+        int commHdl = accept(listenHdl, (struct sockaddr *) &remote, &len);+        if (commHdl == -1) {+            barf("accept failed %s", strerror(errno));         }-        handle_connection(s2);+        +        // Handle and on disconnect listen for more connections+        handle_connection(commHdl);     } }  extern "C" StgWord saveClosures(StgWord n, HsStablePtr *sps) {-    struct savedObjectsState *ps = &g_savedObjectState;     StgWord i;      if(n > maxSavedObjects)         return maxSavedObjects;      for (i = 0; i < n; i++) {-        ps->objects[i] = sps[i];+        g_savedObjectState.objects[i] = sps[i];     }-    ps->n_objects = i;+    g_savedObjectState.n_objects = i;     return 0; } 
ghc-debug-stub.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.4 name:                ghc-debug-stub-version:             0.2.1.0+version:             0.3.0.0 synopsis:            Functions for instrumenting your application so the heap                      can be analysed with ghc-debug-common. description:         Functions for instrumenting your application so the heap can@@ -27,12 +27,12 @@                      , directory ^>= 1.3                      , filepath ^>= 1.4                      , ghc-prim ^>= 0.8-                     , ghc-debug-convention == 0.2.0.0+                     , ghc-debug-convention == 0.3.0.0   default-language:    Haskell2010   cxx-sources:         cbits/stub.cpp, cbits/socket.cpp, cbits/trace.cpp-  cxx-options:         -std=gnu++11 -O3 -g3 -DTHREADED_RTS+  cxx-options:         -std=gnu++11 -pthread -O3 -g3 -DTHREADED_RTS   extra-libraries:     stdc++   cpp-options: -DTHREADED_RTS   if flag(trace)-    cpp-options: -DTRACE+    cxx-options: -DTRACE