From 51292c247228d5ae0c961bd603153ab73495b5d4 Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Sat, 4 Jun 2016 23:48:03 +0200
Subject: [PATCH] event_selector does not deal with socket anymore

It was wrong.
Plus it is starting work so as to make enb.c not crashing if
the tracee goes away (maybe also textlog and vcd, but those are of
less importance).
---
 common/utils/T/tracer/enb.c            | 52 +++++++++++++++++--------
 common/utils/T/tracer/event_selector.c | 36 ++++++++---------
 common/utils/T/tracer/event_selector.h |  4 +-
 common/utils/T/tracer/textlog.c        | 54 ++++++++++++++++++--------
 common/utils/T/tracer/vcd.c            | 52 +++++++++++++++++--------
 5 files changed, 128 insertions(+), 70 deletions(-)

diff --git a/common/utils/T/tracer/enb.c b/common/utils/T/tracer/enb.c
index c80fd9bda3..eeaa0ff31f 100644
--- a/common/utils/T/tracer/enb.c
+++ b/common/utils/T/tracer/enb.c
@@ -1,7 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
+#include <pthread.h>
 #include "database.h"
 #include "event.h"
 #include "handler.h"
@@ -19,9 +19,34 @@ typedef struct {
   view *legacy;
 } enb_gui;
 
+typedef struct {
+  int socket;
+  int *is_on;
+  int nevents;
+  pthread_mutex_t lock;
+} enb_data;
+
 #define DEFAULT_REMOTE_IP "127.0.0.1"
 #define DEFAULT_REMOTE_PORT 2021
 
+void is_on_changed(void *_d)
+{
+  enb_data *d = _d;
+  char t;
+
+  if (pthread_mutex_lock(&d->lock)) abort();
+
+  if (d->socket == -1) goto no_connection;
+
+  t = 1;
+  socket_send(d->socket, &t, 1);
+  socket_send(d->socket, &d->nevents, sizeof(int));
+  socket_send(d->socket, d->is_on, d->nevents * sizeof(int));
+
+no_connection:
+  if (pthread_mutex_unlock(&d->lock)) abort();
+}
+
 void usage(void)
 {
   printf(
@@ -214,13 +239,11 @@ int main(int n, char **v)
   int on_off_n = 0;
   int *is_on;
   int number_of_events;
-  int s;
   int i;
-  char t;
-  int l;
   event_handler *h;
   gui *g;
   enb_gui eg;
+  enb_data enb_data;
 
   on_off_name = malloc(n * sizeof(char *)); if (on_off_name == NULL) abort();
   on_off_action = malloc(n * sizeof(int)); if (on_off_action == NULL) abort();
@@ -346,25 +369,22 @@ int main(int n, char **v)
   for (i = 0; i < on_off_n; i++)
     on_off(database, on_off_name[i], is_on, on_off_action[i]);
 
-  s = connect_to(ip, port);
+  enb_data.socket = -1;
+  enb_data.is_on = is_on;
+  enb_data.nevents = number_of_events;
+  if (pthread_mutex_init(&enb_data.lock, NULL)) abort();
+  setup_event_selector(g, database, is_on, is_on_changed, &enb_data);
 
-  /* send the first message - activate selected traces */
-  t = 0;
-  if (write(s, &t, 1) != 1) abort();
-  l = 0;
-  for (i = 0; i < number_of_events; i++) if (is_on[i]) l++;
-  if (write(s, &l, sizeof(int)) != sizeof(int)) abort();
-  for (l = 0; l < number_of_events; l++)
-    if (is_on[l])
-      if (write(s, &l, sizeof(int)) != sizeof(int)) abort();
+  enb_data.socket = connect_to(ip, port);
 
-  setup_event_selector(g, database, s, is_on);
+  /* send the first message - activate selected traces */
+  is_on_changed(&enb_data);
 
   /* read messages */
   while (1) {
     char v[T_BUFFER_MAX];
     event e;
-    e = get_event(s, v, database);
+    e = get_event(enb_data.socket, v, database);
     handle_event(h, e);
   }
 
diff --git a/common/utils/T/tracer/event_selector.c b/common/utils/T/tracer/event_selector.c
index bc1f25f4b7..a03846c056 100644
--- a/common/utils/T/tracer/event_selector.c
+++ b/common/utils/T/tracer/event_selector.c
@@ -7,6 +7,8 @@
 
 struct event_selector {
   int *is_on;
+  int *is_on_paused;    /* when pausing, is_on is set to all 0, this one
+                         * is used to copy back data when un-pausing */
   int red;
   int green;
   gui *g;
@@ -15,12 +17,13 @@ struct event_selector {
   void *database;
   int nevents;
   int ngroups;
-  int socket;
   int paused;
   /* those three widgets used to pause/unpause reception of events */
   widget *parent_widget;
   widget *normal_widget;
   widget *pause_widget;
+  void (*change_callback)(void *change_callback_data);
+  void *change_callback_data;
 };
 
 static void scroll(void *private, gui *g,
@@ -57,7 +60,6 @@ static void click(void *private, gui *g,
   char *text;
   int color;
   int i;
-  char t;
 
   /* notification_data depends on the kind of widget */
   if (w == this->pause_widget) {
@@ -76,22 +78,17 @@ static void click(void *private, gui *g,
       container_set_child_growable(g, this->parent_widget,
           this->pause_widget, 1);
       /* pause */
-      t = 1;
-      socket_send(this->socket, &t, 1);
-      socket_send(this->socket, &this->nevents, sizeof(int));
-      set_on = 0;
-      for (i = 0; i < this->nevents; i++)
-        socket_send(this->socket, &set_on, sizeof(int));
+      memcpy(this->is_on_paused, this->is_on, this->nevents * sizeof(int));
+      memset(this->is_on, 0, this->nevents * sizeof(int));
+      this->change_callback(this->change_callback_data);
     } else {
       widget_del_child(g, this->parent_widget, this->pause_widget);
       widget_add_child(g, this->parent_widget, this->normal_widget, 0);
       container_set_child_growable(g, this->parent_widget,
           this->normal_widget, 1);
       /* un-pause */
-      t = 1;
-      socket_send(this->socket, &t, 1);
-      socket_send(this->socket, &this->nevents, sizeof(int));
-      socket_send(this->socket, this->is_on, this->nevents * sizeof(int));
+      memcpy(this->is_on, this->is_on_paused, this->nevents * sizeof(int));
+      this->change_callback(this->change_callback_data);
     }
     this->paused = 1 - this->paused;
     return;
@@ -121,14 +118,11 @@ static void click(void *private, gui *g,
     textlist_set_color(this->g, this->groups, line,
         set_on ? this->green : this->red);
 
-  t = 1;
-  socket_send(this->socket, &t, 1);
-  socket_send(this->socket, &this->nevents, sizeof(int));
-  socket_send(this->socket, this->is_on, this->nevents * sizeof(int));
+  this->change_callback(this->change_callback_data);
 }
 
-event_selector *setup_event_selector(gui *g, void *database, int socket,
-    int *is_on)
+event_selector *setup_event_selector(gui *g, void *database, int *is_on,
+    void (*change_callback)(void *), void *change_callback_data)
 {
   struct event_selector *ret;
   widget *win;
@@ -198,6 +192,9 @@ event_selector *setup_event_selector(gui *g, void *database, int socket,
 
   ret->nevents = n;
 
+  ret->is_on_paused = calloc(n, sizeof(int));
+  if (ret->is_on_paused == NULL) abort();
+
   n = database_get_groups(database, &gps);
   for (i = 0; i < n; i++) {
     textlist_add(g, groups, gps[i], -1, FOREGROUND_COLOR);
@@ -213,7 +210,8 @@ event_selector *setup_event_selector(gui *g, void *database, int socket,
   ret->events = events;
   ret->groups = groups;
   ret->database = database;
-  ret->socket = socket;
+  ret->change_callback = change_callback;
+  ret->change_callback_data = change_callback_data;
 
   ret->parent_widget = win_container;
   ret->normal_widget = main_container;
diff --git a/common/utils/T/tracer/event_selector.h b/common/utils/T/tracer/event_selector.h
index 60da0a07e5..dedd79965c 100644
--- a/common/utils/T/tracer/event_selector.h
+++ b/common/utils/T/tracer/event_selector.h
@@ -5,7 +5,7 @@
 
 typedef void event_selector;
 
-event_selector *setup_event_selector(gui *g, void *database, int socket,
-    int *is_on);
+event_selector *setup_event_selector(gui *g, void *database, int *is_on,
+    void (*change_callback)(void *), void *change_callback_data);
 
 #endif /* _EVENT_SELECTOR_H_ */
diff --git a/common/utils/T/tracer/textlog.c b/common/utils/T/tracer/textlog.c
index 6ff36f650c..f7bde62a43 100644
--- a/common/utils/T/tracer/textlog.c
+++ b/common/utils/T/tracer/textlog.c
@@ -1,7 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
+#include <pthread.h>
 #include "database.h"
 #include "event.h"
 #include "handler.h"
@@ -16,6 +16,31 @@
 #define DEFAULT_REMOTE_IP "127.0.0.1"
 #define DEFAULT_REMOTE_PORT 2021
 
+typedef struct {
+  int socket;
+  int *is_on;
+  int nevents;
+  pthread_mutex_t lock;
+} textlog_data;
+
+void is_on_changed(void *_d)
+{
+  textlog_data *d = _d;
+  char t;
+
+  if (pthread_mutex_lock(&d->lock)) abort();
+
+  if (d->socket == -1) goto no_connection;
+
+  t = 1;
+  socket_send(d->socket, &t, 1);
+  socket_send(d->socket, &d->nevents, sizeof(int));
+  socket_send(d->socket, d->is_on, d->nevents * sizeof(int));
+
+no_connection:
+  if (pthread_mutex_unlock(&d->lock)) abort();
+}
+
 void usage(void)
 {
   printf(
@@ -58,16 +83,14 @@ int main(int n, char **v)
   int on_off_n = 0;
   int *is_on;
   int number_of_events;
-  int s;
   int i;
-  char t;
-  int l;
   event_handler *h;
   logger *textlog;
   gui *g;
   int gui_mode = 0;
   view *out;
   int gui_active = 1;
+  textlog_data textlog_data;
 
   on_off_name = malloc(n * sizeof(char *)); if (on_off_name == NULL) abort();
   on_off_action = malloc(n * sizeof(int)); if (on_off_action == NULL) abort();
@@ -141,26 +164,23 @@ int main(int n, char **v)
   for (i = 0; i < on_off_n; i++)
     on_off(database, on_off_name[i], is_on, on_off_action[i]);
 
-  s = connect_to(ip, port);
+  textlog_data.socket = -1;
+  textlog_data.is_on = is_on;
+  textlog_data.nevents = number_of_events;
+  if (pthread_mutex_init(&textlog_data.lock, NULL)) abort();
+  if (gui_active)
+    setup_event_selector(g, database, is_on, is_on_changed, &textlog_data);
 
-  /* send the first message - activate selected traces */
-  t = 0;
-  if (write(s, &t, 1) != 1) abort();
-  l = 0;
-  for (i = 0; i < number_of_events; i++) if (is_on[i]) l++;
-  if (write(s, &l, sizeof(int)) != sizeof(int)) abort();
-  for (l = 0; l < number_of_events; l++)
-    if (is_on[l])
-      if (write(s, &l, sizeof(int)) != sizeof(int)) abort();
+  textlog_data.socket = connect_to(ip, port);
 
-  if (gui_active)
-    setup_event_selector(g, database, s, is_on);
+  /* send the first message - activate selected traces */
+  is_on_changed(&textlog_data);
 
   /* read messages */
   while (1) {
     char v[T_BUFFER_MAX];
     event e;
-    e = get_event(s, v, database);
+    e = get_event(textlog_data.socket, v, database);
     handle_event(h, e);
   }
 
diff --git a/common/utils/T/tracer/vcd.c b/common/utils/T/tracer/vcd.c
index bf66bddd29..46187f751b 100644
--- a/common/utils/T/tracer/vcd.c
+++ b/common/utils/T/tracer/vcd.c
@@ -1,7 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
+#include <pthread.h>
 #include "database.h"
 #include "event.h"
 #include "handler.h"
@@ -13,6 +13,31 @@
 #include "event_selector.h"
 #include "config.h"
 
+typedef struct {
+  int socket;
+  int *is_on;
+  int nevents;
+  pthread_mutex_t lock;
+} vcd_data;
+
+void is_on_changed(void *_d)
+{
+  vcd_data *d = _d;
+  char t;
+
+  if (pthread_mutex_lock(&d->lock)) abort();
+
+  if (d->socket == -1) goto no_connection;
+
+  t = 1;
+  socket_send(d->socket, &t, 1);
+  socket_send(d->socket, &d->nevents, sizeof(int));
+  socket_send(d->socket, d->is_on, d->nevents * sizeof(int));
+
+no_connection:
+  if (pthread_mutex_unlock(&d->lock)) abort();
+}
+
 #define DEFAULT_REMOTE_IP "127.0.0.1"
 #define DEFAULT_REMOTE_PORT 2021
 
@@ -98,12 +123,10 @@ int main(int n, char **v)
   int on_off_n = 0;
   int *is_on;
   int number_of_events;
-  int s;
   int i;
-  char t;
-  int l;
   event_handler *h;
   gui *g;
+  vcd_data vcd_data;
 
   on_off_name = malloc(n * sizeof(char *)); if (on_off_name == NULL) abort();
   on_off_action = malloc(n * sizeof(int)); if (on_off_action == NULL) abort();
@@ -152,25 +175,22 @@ int main(int n, char **v)
   for (i = 0; i < on_off_n; i++)
     on_off(database, on_off_name[i], is_on, on_off_action[i]);
 
-  s = connect_to(ip, port);
+  vcd_data.socket = -1;
+  vcd_data.is_on = is_on;
+  vcd_data.nevents = number_of_events;
+  if (pthread_mutex_init(&vcd_data.lock, NULL)) abort();
+  setup_event_selector(g, database, is_on, is_on_changed, &vcd_data);
 
-  /* send the first message - activate selected traces */
-  t = 0;
-  if (write(s, &t, 1) != 1) abort();
-  l = 0;
-  for (i = 0; i < number_of_events; i++) if (is_on[i]) l++;
-  if (write(s, &l, sizeof(int)) != sizeof(int)) abort();
-  for (l = 0; l < number_of_events; l++)
-    if (is_on[l])
-      if (write(s, &l, sizeof(int)) != sizeof(int)) abort();
+  vcd_data.socket = connect_to(ip, port);
 
-  setup_event_selector(g, database, s, is_on);
+  /* send the first message - activate selected traces */
+  is_on_changed(&vcd_data);
 
   /* read messages */
   while (1) {
     char v[T_BUFFER_MAX];
     event e;
-    e = get_event(s, v, database);
+    e = get_event(vcd_data.socket, v, database);
     handle_event(h, e);
   }
 
-- 
GitLab