ecore-evas.
SVN revision: 75194
* Correctly shutdown Ecore_Thread.
* Add a way to reset Ecore_Thread internal pipe after a fork via ecore_fork_reset.
+
+2012-08-13 Carsten Haitzler (The Rasterman)
+
+ * Fix ecore fork reset function to allow for callbacks to be
+ attached so ecore-evas can reset evas async fd on fork.
+
EAPI int ecore_init(void);
EAPI int ecore_shutdown(void);
/**
- * Reset the ecore internal state after a fork
- *
- * Ecore maintains internal data that can be affected by the fork() system call
- * which creates a duplicate of the current process. This also duplicates
- * file descriptors which is problematic in that these file descriptors still
- * point to their original sources. This function makes ecore reset internal
- * state (e.g. pipes used for signalling between threads) so they function
- * correctly afterwards.
- *
- * It is highly suggested that you call this function after any fork()
- * system call inside the child process if you intend to use ecore features
- * after this point and not call any exec() family functions. Not doing so
- * will cause possible misbehaviour.
- *
- * @since 1.7
- */
-EAPI void ecore_fork_reset(void);
-
-/**
* @}
*/
typedef void *(*Ecore_Data_Cb)(void *data);
/**
+ * Add a function to be called by ecore_fork_reset()
+ *
+ * This queues @p func to be called (and passed @p data as its argument) when
+ * ecore_fork_reset() is called. This allows other libraries and subsystems
+ * to also reset their internal state after a fork.
+ *
+ * @since 1.7
+ */
+EAPI Eina_Bool ecore_fork_reset_callback_add(Ecore_Cb func, const void *data);
+
+/**
+ * This removes the callback specified
+ *
+ * This deletes the callback added by ecore_fork_reset_callback_add() using
+ * the function and data pointer to specify which to remove.
+ *
+ * @since 1.7
+ */
+EAPI Eina_Bool ecore_fork_reset_callback_del(Ecore_Cb func, const void *data);
+
+/**
+ * Reset the ecore internal state after a fork
+ *
+ * Ecore maintains internal data that can be affected by the fork() system call
+ * which creates a duplicate of the current process. This also duplicates
+ * file descriptors which is problematic in that these file descriptors still
+ * point to their original sources. This function makes ecore reset internal
+ * state (e.g. pipes used for signalling between threads) so they function
+ * correctly afterwards.
+ *
+ * It is highly suggested that you call this function after any fork()
+ * system call inside the child process if you intend to use ecore features
+ * after this point and not call any exec() family functions. Not doing so
+ * will cause possible misbehaviour.
+ *
+ * @since 1.7
+ */
+EAPI void ecore_fork_reset(void);
+
+/**
* @brief Call callback asynchronously in the main loop.
* @since 1.1.0
*
return _ecore_init_count;
}
+struct _Ecore_Fork_Cb
+{
+ Ecore_Cb func;
+ void *data;
+ Eina_Bool delete_me : 1;
+};
+
+typedef struct _Ecore_Fork_Cb Ecore_Fork_Cb;
+
+static int fork_cbs_walking = 0;
+static Eina_List *fork_cbs = NULL;
+
+EAPI Eina_Bool
+ecore_fork_reset_callback_add(Ecore_Cb func, const void *data)
+{
+ Ecore_Fork_Cb *fcb;
+
+ fcb = calloc(1, sizeof(Ecore_Fork_Cb));
+ if (!fcb) return EINA_FALSE;
+ fcb->func = func;
+ fcb->data = (void *)data;
+ fork_cbs = eina_list_append(fork_cbs, fcb);
+ return EINA_TRUE;
+}
+
+EAPI Eina_Bool
+ecore_fork_reset_callback_del(Ecore_Cb func, const void *data)
+{
+ Eina_List *l;
+ Ecore_Fork_Cb *fcb;
+
+ EINA_LIST_FOREACH(fork_cbs, l, fcb)
+ {
+ if ((fcb->func == func) && (fcb->data == data))
+ {
+ if (!fork_cbs_walking)
+ {
+ fork_cbs = eina_list_remove_list(fork_cbs, l);
+ free(fcb);
+ }
+ else
+ fcb->delete_me = EINA_TRUE;
+ return EINA_TRUE;
+ }
+ }
+ return EINA_FALSE;
+}
+
EAPI void
ecore_fork_reset(void)
{
+ Eina_List *l, *ln;
+ Ecore_Fork_Cb *fcb;
+
eina_lock_take(&_thread_safety);
ecore_pipe_del(_thread_call);
if (_thread_cb) ecore_pipe_write(_thread_call, &wakeup, sizeof (int));
eina_lock_release(&_thread_safety);
+
+ // should this be done withing the eina lock stuff?
+
+ fork_cbs_walking++;
+ EINA_LIST_FOREACH(fork_cbs, l, fcb)
+ {
+ fcb->func(fcb->data);
+ }
+ fork_cbs_walking--;
+
+ EINA_LIST_FOREACH_SAFE(fork_cbs, l, ln, fcb)
+ {
+ if (fcb->delete_me)
+ {
+ fork_cbs = eina_list_remove_list(fork_cbs, l);
+ free(fcb);
+ }
+ }
}
/**
};
}
+static void
+_ecore_evas_fork_cb(void *data __UNUSED__)
+{
+ int fd;
+
+ if (_ecore_evas_async_events_fd)
+ ecore_main_fd_handler_del(_ecore_evas_async_events_fd);
+ fd = evas_async_events_fd_get();
+ if (fd >= 0)
+ _ecore_evas_async_events_fd =
+ ecore_main_fd_handler_add(fd, ECORE_FD_READ,
+ _ecore_evas_async_events_fd_handler, NULL,
+ NULL, NULL);
+}
+
EAPI int
ecore_evas_init(void)
{
goto shutdown_ecore;
}
+ ecore_fork_reset_callback_add(_ecore_evas_fork_cb, NULL);
fd = evas_async_events_fd_get();
- if (fd > 0)
- _ecore_evas_async_events_fd = ecore_main_fd_handler_add(fd,
- ECORE_FD_READ,
- _ecore_evas_async_events_fd_handler, NULL,
- NULL, NULL);
+ if (fd >= 0)
+ _ecore_evas_async_events_fd =
+ ecore_main_fd_handler_add(fd, ECORE_FD_READ,
+ _ecore_evas_async_events_fd_handler, NULL,
+ NULL, NULL);
ecore_evas_idle_enterer =
ecore_idle_enterer_add(_ecore_evas_idle_enter, NULL);
if (_ecore_evas_async_events_fd)
ecore_main_fd_handler_del(_ecore_evas_async_events_fd);
+
+ ecore_fork_reset_callback_del(_ecore_evas_fork_cb, NULL);
eina_log_domain_unregister(_ecore_evas_log_dom);
_ecore_evas_log_dom = -1;