raster pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=030ef36c72b721de487ca3bb940d4f22a58e745c

commit 030ef36c72b721de487ca3bb940d4f22a58e745c
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
Date:   Wed Mar 25 16:46:27 2020 +0000

    emotion - webcam - fix segv on webcam plug/unplug and clean
    
    well hunting was fun... custom webcams i just cant see being used. no
    api to add them - have to hand craft a config file .. and udev/eeze
    provide info on webcam devices anyway at runtime with plug/unplug etc.
    ... so this should be the only ay (for now) and it keesp the code
    simpler and less bug-prone
    
    now issue was some nasty skipping unref as opposed to destroy. in
    chasing i simplified the code to help me narrow it down and not chase
    the same logic in multiple places. shorter cleaere, simpler and minux
    one bug.
    
    @fix
---
 src/lib/emotion/emotion_main.c    |   1 -
 src/lib/emotion/emotion_private.h |   1 -
 src/lib/emotion/emotion_webcam.c  | 284 +++++++++++++-------------------------
 3 files changed, 95 insertions(+), 191 deletions(-)

diff --git a/src/lib/emotion/emotion_main.c b/src/lib/emotion/emotion_main.c
index d641621105..f9ab316b09 100644
--- a/src/lib/emotion/emotion_main.c
+++ b/src/lib/emotion/emotion_main.c
@@ -173,7 +173,6 @@ emotion_init(void)
    _emotion_config_file = eet_open(buffer, EET_FILE_MODE_READ);
 
    if (!emotion_webcam_init()) goto error_webcam;
-   emotion_webcam_config_load(_emotion_config_file);
 
    if (!emotion_modules_init()) goto error_modules;
 
diff --git a/src/lib/emotion/emotion_private.h 
b/src/lib/emotion/emotion_private.h
index 34e2bc3c9b..972224e5d1 100644
--- a/src/lib/emotion/emotion_private.h
+++ b/src/lib/emotion/emotion_private.h
@@ -7,7 +7,6 @@
 
 Eina_Bool emotion_webcam_init(void);
 void emotion_webcam_shutdown(void);
-Eina_Bool emotion_webcam_config_load(Eet_File *ef);
 
 Eina_Bool emotion_modules_init(void);
 void emotion_modules_shutdown(void);
diff --git a/src/lib/emotion/emotion_webcam.c b/src/lib/emotion/emotion_webcam.c
index d29110aa23..8b46b9a724 100644
--- a/src/lib/emotion/emotion_webcam.c
+++ b/src/lib/emotion/emotion_webcam.c
@@ -27,11 +27,9 @@ typedef struct _Emotion_Webcams Emotion_Webcams;
 struct _Emotion_Webcams
 {
    Eina_List *webcams;
-
    Ecore_Idler *idler;
    Eina_List *check_list;
-
-   Eina_Bool init;
+   Eina_Bool init : 1;
 };
 
 struct _Emotion_Webcam
@@ -41,56 +39,18 @@ struct _Emotion_Webcam
    const char *syspath;
    const char *device;
    const char *name;
-
-   const char *custom;
-
    const char *filename;
+   Eina_Bool in_list : 1;
 };
 
-static Eet_Data_Descriptor *_webcam_edd;
-static Eet_Data_Descriptor *_webcams_edd;
-
 static Emotion_Webcams *_emotion_webcams = NULL;
 
-static Eet_Data_Descriptor *
-_emotion_webcams_edds_new(void)
-{
-   Eet_Data_Descriptor_Class eddc;
-
-   EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcam);
-   _webcam_edd = eet_data_descriptor_file_new(&eddc);
-   EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "device", 
device, EET_T_STRING);
-   EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "name", name, 
EET_T_STRING);
-   EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "custom", 
custom, EET_T_STRING);
-   EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcam, "filename", 
filename, EET_T_STRING);
-
-   EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Emotion_Webcams);
-   _webcams_edd = eet_data_descriptor_file_new(&eddc);
-   EET_DATA_DESCRIPTOR_ADD_LIST(_webcams_edd, Emotion_Webcams, "webcams", 
webcams, _webcam_edd);
-   EET_DATA_DESCRIPTOR_ADD_BASIC(_webcam_edd, Emotion_Webcams, "init", init, 
EET_T_CHAR);
-
-   return _webcams_edd;
-}
-
-static void
-_emotion_webcams_edds_free(void)
-{
-   eet_data_descriptor_free(_webcams_edd);
-   _webcams_edd = NULL;
-
-   eet_data_descriptor_free(_webcam_edd);
-   _webcam_edd = NULL;
-}
-
 static void
 emotion_webcam_destroy(Emotion_Webcam *ew)
 {
-   if (!ew->custom)
-     {
-        eina_stringshare_del(ew->syspath);
-        eina_stringshare_del(ew->device);
-        eina_stringshare_del(ew->name);
-     }
+   eina_stringshare_del(ew->syspath);
+   eina_stringshare_del(ew->device);
+   eina_stringshare_del(ew->name);
    free(ew);
 }
 
@@ -116,33 +76,25 @@ _emotion_check_device(Emotion_Webcam *ew)
 
    if (ioctl(fd, VIDIOC_QUERYCAP, &caps) == -1) goto on_error;
 
-   /* Likely not a webcam */
+   // Likely not a webcam
    if (!(caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)) goto on_error;
-   if (caps.capabilities & V4L2_CAP_TUNER
-       || caps.capabilities & V4L2_CAP_RADIO
-       || caps.capabilities & V4L2_CAP_MODULATOR)
+   if (caps.capabilities &
+       (V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_MODULATOR))
      goto on_error;
 
    EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check)
-     if (check->device == ew->device)
-       goto on_error;
-
+     {
+        if (check->device == ew->device) goto on_error;
+     }
    _emotion_webcams->webcams = eina_list_append(_emotion_webcams->webcams, ew);
-
-   EINA_REFCOUNT_INIT(ew);
-
+   ew->in_list = EINA_TRUE;
    if (fd >= 0) close(fd);
-
    return EINA_TRUE;
 
  on_error:
 #endif
    INF("'%s' is not a webcam ['%s']", ew->name, strerror(errno));
-   _emotion_webcams->webcams = eina_list_remove(_emotion_webcams->webcams, ew);
-   eina_stringshare_del(ew->syspath);
-   eina_stringshare_del(ew->device);
-   eina_stringshare_del(ew->name);
-   free(ew);
+   emotion_webcam_destroy(ew);
 #ifdef HAVE_V4L2
    if (fd >= 0) close(fd);
 #endif
@@ -152,109 +104,113 @@ _emotion_check_device(Emotion_Webcam *ew)
 static Emotion_Webcam *
 _emotion_webcam_new(const char *syspath)
 {
-   Emotion_Webcam *test;
+   Emotion_Webcam *ew;
    const char *device;
    char *local;
 
-   test = malloc(sizeof (Emotion_Webcam));
-   if (!test) return NULL;
+   ew = calloc(1, sizeof(Emotion_Webcam));
+   if (!ew) return NULL;
 
-   test->custom = NULL;
-   test->syspath = eina_stringshare_ref(syspath);
-   test->name = eeze_udev_syspath_get_sysattr(syspath, "name");
+   EINA_REFCOUNT_INIT(ew);
+   ew->syspath = eina_stringshare_ref(syspath);
+   ew->name = eeze_udev_syspath_get_sysattr(syspath, "name");
 
    device = eeze_udev_syspath_get_property(syspath, "DEVNAME");
    local = alloca(eina_stringshare_strlen(device) + 8);
    snprintf(local, eina_stringshare_strlen(device) + 8, "v4l2://%s", device);
-   test->device = eina_stringshare_add(local);
+   ew->device = eina_stringshare_add(local);
    eina_stringshare_del(device);
-   test->filename = test->device + 7;
+   ew->filename = ew->device + 7;
 
-   return test;
+   return ew;
 }
 
 static void
-_emotion_webcam_remove_cb(void *user_data, void *func_data EINA_UNUSED)
+_emotion_webcam_unref(Emotion_Webcam *ew)
 {
-   Emotion_Webcam *webcam;
-
-   /* called at the end of EMOTION_WEBCAM_ADD event, to prevent the free */
-   if (!user_data)
-     return;
-
-   webcam = user_data;
-
-   EINA_REFCOUNT_UNREF(webcam)
+   EINA_REFCOUNT_UNREF(ew)
      {
-        if (_emotion_webcams)
-          _emotion_webcams->webcams =
-          eina_list_remove(_emotion_webcams->webcams, webcam);
-        emotion_webcam_destroy(webcam);
+        if ((ew->in_list) && (_emotion_webcams))
+          {
+             _emotion_webcams->webcams =
+               eina_list_remove(_emotion_webcams->webcams, ew);
+             ew->in_list = EINA_FALSE;
+          }
+        emotion_webcam_destroy(ew);
      }
 }
 
+static void
+_emotion_eeze_event_free(void *data EINA_UNUSED, void *ev)
+{
+   _emotion_webcam_unref(ev);
+}
+
+static void
+_emotion_webcam_ev_add(const char *syspath)
+{
+   Emotion_Webcam *ew = _emotion_webcam_new(syspath);
+   if (!ew) return;
+   if (!_emotion_check_device(ew)) return;
+   EINA_REFCOUNT_REF(ew);
+   ecore_event_add(EMOTION_WEBCAM_ADD, ew, _emotion_eeze_event_free, NULL);
+}
+
 static Eina_Bool
 _emotion_process_webcam(void *data)
 {
-   Emotion_Webcams *webcams;
-   Emotion_Webcam *test;
+   Emotion_Webcams *webcams = data;
    const char *syspath;
 
-   webcams = data;
    syspath = eina_list_data_get(webcams->check_list);
    if (!syspath)
      {
-       webcams->idler = NULL;
-       webcams->init = EINA_TRUE;
-       return EINA_FALSE;
+        webcams->idler = NULL;
+        webcams->init = EINA_TRUE;
+        return EINA_FALSE;
      }
-
    webcams->check_list = eina_list_remove_list(webcams->check_list,
-                                              webcams->check_list);
-
-   test = _emotion_webcam_new(syspath);
-   if (test)
-     {
-       if (_emotion_check_device(test))
-         ecore_event_add(EMOTION_WEBCAM_ADD, test, NULL, NULL);
-     }
-
+                                               webcams->check_list);
+   _emotion_webcam_ev_add(syspath);
    eina_stringshare_del(syspath);
-
    return EINA_TRUE;
 }
 
 static void
-_emotion_eeze_events(const char *syspath,
-                     Eeze_Udev_Event ev,
+_emotion_webcam_remove_cb(void *data EINA_UNUSED, void *ev)
+{
+   _emotion_webcam_unref(ev);
+}
+
+static void
+_emotion_eeze_events(const char *syspath, Eeze_Udev_Event ev,
                      void *data EINA_UNUSED,
                      Eeze_Udev_Watch *watcher EINA_UNUSED)
 {
    if (ev == EEZE_UDEV_EVENT_REMOVE)
      {
-        Emotion_Webcam *check;
-       Eina_List *l;
-
-        EINA_LIST_FOREACH(_emotion_webcams->webcams, l, check)
-          if (check->syspath == syspath)
-            {
-               _emotion_webcams->webcams =
-                  eina_list_remove_list(_emotion_webcams->webcams, l);
-               ecore_event_add(EMOTION_WEBCAM_DEL, check,
-                               _emotion_webcam_remove_cb, check);
-               break ;
-            }
+        Emotion_Webcam *ew;
+        Eina_List *l;
+
+        EINA_LIST_FOREACH(_emotion_webcams->webcams, l, ew)
+          {
+             if (ew->syspath == syspath)
+               {
+                  if (ew->in_list)
+                    {
+                       _emotion_webcams->webcams =
+                         eina_list_remove_list(_emotion_webcams->webcams, l);
+                       ew->in_list = EINA_FALSE;
+                    }
+                  ecore_event_add(EMOTION_WEBCAM_DEL, ew,
+                                  _emotion_webcam_remove_cb, NULL);
+                  break;
+               }
+          }
      }
    else if (ev == EEZE_UDEV_EVENT_ADD)
      {
-        Emotion_Webcam *test;
-
-        test = _emotion_webcam_new(syspath);
-        if (test)
-         {
-            if (_emotion_check_device(test))
-              ecore_event_add(EMOTION_WEBCAM_ADD, test, NULL, NULL);
-         }
+        _emotion_webcam_ev_add(syspath);
      }
    ecore_event_add(EMOTION_WEBCAM_UPDATE, NULL, NULL, NULL);
 }
@@ -266,12 +222,11 @@ _emotion_enumerate_all_webcams(void)
 {
 #ifdef HAVE_EEZE
    Eina_List *devices;
-   if (_emotion_webcams->init) return ;
+   if (_emotion_webcams->init) return;
    devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_V4L, NULL);
-
    _emotion_webcams->check_list = devices;
    _emotion_webcams->idler = ecore_idler_add(_emotion_process_webcam,
-                                            _emotion_webcams);
+                                             _emotion_webcams);
 #endif
 }
 
@@ -282,9 +237,6 @@ Eina_Bool emotion_webcam_init(void)
    EMOTION_WEBCAM_ADD = ecore_event_type_new();
    EMOTION_WEBCAM_DEL = ecore_event_type_new();
 
-   eet_init();
-   _emotion_webcams_edds_new();
-
    if (!_emotion_webcams)
      {
         _emotion_webcams = calloc(1, sizeof (Emotion_Webcams));
@@ -293,10 +245,9 @@ Eina_Bool emotion_webcam_init(void)
 
 #ifdef HAVE_EEZE
    eeze_init();
-
-   eeze_watcher = eeze_udev_watch_add(EEZE_UDEV_TYPE_V4L,
-                                      (EEZE_UDEV_EVENT_ADD | 
EEZE_UDEV_EVENT_REMOVE),
-                                      _emotion_eeze_events, NULL);
+   eeze_watcher = eeze_udev_watch_add
+     (EEZE_UDEV_TYPE_V4L, (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE),
+     _emotion_eeze_events, NULL);
 #endif
 
    return EINA_TRUE;
@@ -308,8 +259,7 @@ emotion_webcam_shutdown(void)
    Emotion_Webcam *ew;
    const char *syspath;
 
-   ecore_event_type_flush(EMOTION_WEBCAM_UPDATE,
-                          EMOTION_WEBCAM_ADD,
+   ecore_event_type_flush(EMOTION_WEBCAM_UPDATE, EMOTION_WEBCAM_ADD,
                           EMOTION_WEBCAM_DEL);
 
    if (_emotion_webcams->idler)
@@ -319,15 +269,21 @@ emotion_webcam_shutdown(void)
      }
 
    EINA_LIST_FREE(_emotion_webcams->check_list, syspath)
-     eina_stringshare_del(syspath);
+     {
+        eina_stringshare_del(syspath);
+     }
 
    _emotion_webcams->init = EINA_FALSE;
 
    EINA_LIST_FREE(_emotion_webcams->webcams, ew)
      {
-        /* There is currently no way to refcount from the outside, this help, 
but could lead to some issue */
+        ew->in_list = EINA_FALSE;
+        // There is currently no way to refcount from the outside, this helps
+        // but could lead to some issues
         EINA_REFCOUNT_UNREF(ew)
-          emotion_webcam_destroy(ew);
+          {
+             emotion_webcam_destroy(ew);
+          }
      }
    free(_emotion_webcams);
    _emotion_webcams = NULL;
@@ -335,54 +291,15 @@ emotion_webcam_shutdown(void)
 #ifdef HAVE_EEZE
    eeze_udev_watch_del(eeze_watcher);
    eeze_watcher = NULL;
-
    eeze_shutdown();
 #endif
-
-   _emotion_webcams_edds_free();
-   eet_shutdown();
-}
-
-Eina_Bool
-emotion_webcam_config_load(Eet_File *ef)
-{
-   Emotion_Webcams *emotion_webcams = NULL;
-
-   if (ef)
-     {
-        emotion_webcams = eet_data_read(ef, _webcams_edd, "config");
-        INF("Loaded config %p from eet %s", _emotion_webcams, 
eet_file_get(ef));
-     }
-
-   if (emotion_webcams)
-     {
-        if (_emotion_webcams)
-          {
-             emotion_webcam_shutdown();
-             _emotion_webcams = emotion_webcams;
-             emotion_webcam_init();
-          }
-        else
-          _emotion_webcams = emotion_webcams;
-     }
-
-   if (!_emotion_webcams)
-     {
-        DBG("No config, create empty");
-        _emotion_webcams = calloc(1, sizeof (Emotion_Webcams));
-        EINA_SAFETY_ON_NULL_RETURN_VAL(_emotion_webcams, EINA_FALSE);
-     }
-
-   return EINA_TRUE;
 }
 
 EAPI const Eina_List *
 emotion_webcams_get(void)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(_emotion_webcams, NULL);
-
    _emotion_enumerate_all_webcams();
-
    return _emotion_webcams->webcams;
 }
 
@@ -401,18 +318,7 @@ emotion_webcam_device_get(const Emotion_Webcam *ew)
 }
 
 EAPI const char *
-emotion_webcam_custom_get(const char *device)
+emotion_webcam_custom_get(const char *device EINA_UNUSED)
 {
-   const Emotion_Webcam *ew;
-   const Eina_List *l;
-
-   EINA_SAFETY_ON_NULL_RETURN_VAL(_emotion_webcams, NULL);
-
-   _emotion_enumerate_all_webcams();
-
-   EINA_LIST_FOREACH(_emotion_webcams->webcams, l, ew)
-     if (ew->device && strcmp(device, ew->device) == 0)
-       return ew->custom;
-
    return NULL;
 }

-- 


Reply via email to