LTTV trace control bug fix
authorChris Smowton <cs448@cam.ac.uk>
Wed, 18 Nov 2009 17:49:12 +0000 (12:49 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Wed, 18 Nov 2009 17:49:12 +0000 (12:49 -0500)
Chris Smowton <cs448@cam.ac.uk>:

...whenever I tried
to start a trace using the GUI, it would freeze consuming 100% CPU after
I clicked "start". Turned out this was because in tracecontrol.c's
start_clicked callback, you poll(2) on an FD and use a switch()
statement to handle its return.

Unfortunately, poll(2) doesn't work that way -- it returns a *mask* of
bits, not a single value. Here poll was returning POLLIN | POLLHUP to
indicate there's data ready and the FD has been closed by the other
side, and since this != POLLIN and != POLLHUP, the poll loop spins
forever.

Attached is a patch to be applied to tracecontrol.c which fixes it to
check for set-bits instead. It's still strictly broken, as the read(fd,
buf, 256) call might not fully drain the child's output, but it's a step
in the right direction and means I can at least use the trace-control
thing.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
lttv/modules/gui/tracecontrol/tracecontrol.c

index 28e665567baf7374310868c7c8d9212091ba3e91..283674b726650428a6ffc1d66f4db1bd51173617 100644 (file)
@@ -513,56 +513,61 @@ static int execute_command(const gchar *command, const gchar *username,
       /* Timeout : Stop waiting for chars */
       if(num_rdy == 0) goto wait_child;
 
-      switch(pollfd.revents) {
-        case POLLERR:
+      /* Check for fatal errors */
+      if(pollfd.revents & POLLERR) {
           g_warning("Error returned in polling fd\n");
           num_hup++;
-          break;
-        case POLLHUP:
-          g_info("Polling FD : hung up.");
-          num_hup++;
-          break;
-        case POLLNVAL:
-          g_warning("Polling fd tells it is not open");
-          num_hup++;
-          break;
-        case POLLPRI:
-        case POLLIN:
-          count = read (fdpty, buf, 256);
-          if(count > 0) {
-                                               unsigned int i;
-            buf[count] = '\0';
-            g_printf("%s", buf);
-                                               for(i=0; i<count; i++) {
-                                                       switch(read_state) {
-                                                               case GET_LINE:
-                                                                       if(buf[i] == '\n') {
-                                                                               read_state = GET_SEMI;
-                                                                               g_debug("Tracecontrol input line skip\n");
-                                                                       }
-                                                                       break;
-                                                               case GET_SEMI:
-                                                                       if(buf[i] == ':') {
-                                                                               g_debug("Tracecontrol input  : marker found\n");
-                                                                               read_state = GET_SPACE;
-                                                                       }
-                                                                       break;
-                                                               case GET_SPACE:
-                                                                       if(buf[i] == ' ') {
-                                                                               g_debug("Tracecontrol input space marker found\n");
-                                                                               goto write_password;
-                                                                       }
-                                                                       break;
-                                                       }
-                                               }
-          } else if(count == -1) {
-            perror("Error in read");
-            goto wait_child;
-          }
-          break;
       }
+      if(pollfd.revents & POLLNVAL) {
+       g_warning("Polling fd tells it is not open");
+       num_hup++;
+      }
+
+      if(pollfd.revents & POLLHUP) {
+
+       g_info("Polling FD : hung up.");
+       num_hup++;
+
+      }
+
+      if(pollfd.revents & (POLLIN | POLLPRI)) {
+       int count;
+       count = read (fdpty, buf, 256);
+       if(count > 0) {
+         unsigned int i;
+         buf[count] = '\0';
+         g_printf("%s", buf);
+         for(i=0; i<count; i++) {
+           switch(read_state) {
+           case GET_LINE:
+             if(buf[i] == '\n') {
+               read_state = GET_SEMI;
+               g_debug("Tracecontrol input line skip\n");
+             }
+             break;
+           case GET_SEMI:
+             if(buf[i] == ':') {
+               g_debug("Tracecontrol input  : marker found\n");
+               read_state = GET_SPACE;
+             }
+             break;
+           case GET_SPACE:
+             if(buf[i] == ' ') {
+               g_debug("Tracecontrol input space marker found\n");
+               goto write_password;
+             }
+             break;
+           }
+         }
+       } else if(count == -1) {
+         perror("Error in read");
+         goto wait_child;
+       }
+
+      }
+
       if(num_hup > 0) {
-        g_warning("Child hung up too fast");
+        g_warning("Child hung up without returning a full reply");
         goto wait_child;
       }
     }
This page took 0.025413 seconds and 4 git commands to generate.