On 06/26/2012 10:37 AM, Jakub Filak wrote:
Signed-off-by: Jakub Filak<[email protected]>
---
  libreport.spec.in            |    1 +
  src/include/Makefile.am      |    3 +-
  src/include/run_event_list.h |  209 ++++++++++++++
  src/lib/Makefile.am          |    3 +-
  src/lib/run_event_list.c     |  618 ++++++++++++++++++++++++++++++++++++++++++
  5 files changed, 832 insertions(+), 2 deletions(-)
  create mode 100644 src/include/run_event_list.h
  create mode 100644 src/lib/run_event_list.c

diff --git a/libreport.spec.in b/libreport.spec.in
index 3f730e3..ea51431 100644
--- a/libreport.spec.in
+++ b/libreport.spec.in
@@ -297,6 +297,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor&>/dev/null 
|| :
  %{_includedir}/libreport/report.h
  %{_includedir}/libreport/run_event.h
  %{_includedir}/libreport/event_usability.h
+%{_includedir}/libreport/run_event_list.h
  # Private api headers:
  %{_includedir}/libreport/internal_abrt_dbus.h
  %{_includedir}/libreport/internal_libreport.h
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 7aa5f78..bca63dd 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -10,4 +10,5 @@ libreport_include_HEADERS = \
      \
      internal_libreport.h \
      internal_abrt_dbus.h \
-    event_usability.h
+    event_usability.h \
+    run_event_list.h
diff --git a/src/include/run_event_list.h b/src/include/run_event_list.h
new file mode 100644
index 0000000..f5fa11f
--- /dev/null
+++ b/src/include/run_event_list.h
@@ -0,0 +1,209 @@
+/*
+    Copyright (C) 2012  ABRT team.
+    Copyright (C) 2012  RedHat inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef LIBREPORT_RUN_EVENT_LIST_H_
+#define LIBREPORT_RUN_EVENT_LIST_H_
+
+#include<glib.h>
+#include "run_event.h"
+#include "event_usability.h"
+
+/* Forward declartion */
+struct event_list_process;
+
+/*
+ * Return value from event list process signal.
+ * Signal handler returns these values in order to adjust process
+ * flow according to current state.
+ */
+enum elp_signal_ret
+{
+    ELPSR_CONTINUE,     ///<  A process should continue with next step.
+    ELPSR_NEXT_EVENT,   ///<  A process should skip all remaining steps a 
continue with next event.
+    ELPSR_FINISH,       ///<  A process should skip all remaining events and 
finis itself.
+};

What is elp[sr]?


+/*
+ * Event list process signal function type

This does not make sense to me.

+ *
+ * @param process A process that emits a signal.
+ * @return A value that adjusts process flow.
+ */
+typedef enum elp_signal_ret (* elp_signal)(struct event_list_process *process);
+
+/*
+ * All signals used by event list process
+ */
+struct elp_signals_impl
+{
+    /*
+     * Next event was successfully selected and process is about to process it
+     */
+    elp_signal next_event_selected;
+
+    /*
+     * Currently selected event requires review.
+     */
+    elp_signal review_data;
+
+    /*
+     * Currently selected event is about to be run.
+     */
+    elp_signal run_event;
+
+    /*
+     * Currently selected event has finished.
+     */
+    elp_signal event_done;
+
+    /*
+     * No more events to be processed
+     */
+    elp_signal finished;
+
+    /*
+     * Event has some problem with configuration
+     */
+    elp_signal configuration_issue;
+};

This looks like a TON of added complexity for no apparent reason.

For starters, what problem are you solving?



+/*
+ * Types of event run result
+ */
+enum elp_event_run_status
+{
+    ELP_ERS_NONE,       ///<  No run was performed
+    ELP_ERS_SUCCESSFUL, ///<  Event finished successfully
+    ELP_ERS_FAILED,     ///<  Event failed
+    ELP_ERS_NOT_FOUND,  ///<  No processing was found
+};

ELP ERS?


+/*
+ * Structure holds an configuration issue info
+ */
+struct elp_configuration_issue
+{
+    const char *event_name;                 ///<  Event with problems
+    enum event_usability_status usability;  ///<  Event usability
+    const GList *issues;                    ///<  All known configuration 
issues for an event
+};
+
+/*
+ * Initializes event list process signal functions.
+ *
+ * @param impl A not NULL pointer to signals
+ */
+void event_list_process_impl_init(struct elp_signals_impl *impl);

I am totally lost by now. What are we doing here?


+/*
+ * Creates an initializes an event list process
+ *
+ * @param events A list of events to be processed, do not take an ownership
+ * @param signals A signal implementation, do not take an ownership
+ * @param run_impl A call backs for event run, do not take an ownership
+ * @param run_obs An observer for event run, do not take an ownership
+ * @param dump_dir_name A dump dir name, do not take an ownership
+ * @param signal_args A custom data available by elp_get_signal_args()
+ * @return An initialized event list process, never returns NULL
+ */
+struct event_list_process *new_event_list_process(const GList *events,
+                                                  const struct 
elp_signals_impl *impl,
+                                                  const struct run_event_impl 
*run_impl,
+                                                  const struct 
run_event_observer *run_obs,
+                                                  const char *dump_dir_name,
+                                                  void *signal_args);
+
+/*
+ * Frees all used memory by an event list process
+ *
+ * @param process A pointer to process
+ */
+void free_event_list_process(struct event_list_process *process);
+
+/*
+ * Gets an currently selected event.
+ *
+ * @param process A not NULL pointer to process
+ * @return A pointer to event name if some event was selected, otherwise 
returns NULL
+ */
+const char *elp_get_current_event(const struct event_list_process *process);
+
+/*
+ * Gets an currently selected event.
+ *
+ * @param process A not NULL pointer to process
+ * @return A data passed in new_event_list_process()
+ */
+void *elp_get_signal_args(const struct event_list_process *process);
+
+/*
+ * Gets the last event run result.
+ *
+ * @param process A not NULL pointer to process
+ * @return the last event run result.
+ */
+enum elp_event_run_status elp_get_last_event_status(const struct 
event_list_process *process);
+
+/*
+ * Gets the last configuraton issue. This function must be called
+ * only from handler of configuration_issue signal.
+ *
+ * @param process A not NULL pointer to process
+ * @return the last configuration issue.
+ */
+const struct elp_configuration_issue *elp_get_last_configuration_issue(const 
struct event_list_process *process);
+
+/*
+ * Sets a post run callback for run_event_state.
+ *
+ * The method is provided only for backward compatibility
+ *
+ * @param process A not NULL pointer to process
+ * @param post_run_callback A pointer to function
+ * @param post_run_param A custom data passed to callback
+ */
+void elp_set_post_run_callback(struct event_list_process *process, 
res_post_run_callback post_run_callback, void *post_run_param);
+
+/*
+ * Sets a logging callback for run_event_state.
+ *
+ * The method is provided only for backward compatibility
+ *
+ * @param process A not NULL pointer to process
+ * @param loggin_callback A pointer to function
+ * @param loggin_param A custom data passed to callback
+ */
+void elp_set_logging_callback(struct event_list_process *process, 
res_logging_callback logging_callback, void *logging_param);
+
+/*
+ * Forces a process to perform next step.
+ *
+ * @param process A not NULL pointer to process
+ * @return 0 if last step was performed; otherwise returns non 0
+ */
+int elp_next_step(struct event_list_process *process);
+
+/*
+ * Kills an event command process
+ *
+ * @param process A not NULL pointer to process
+ */
+void elp_kill_run(struct event_list_process *process);
+
+#endif /* LIBREPORT_RUN_EVENT_LIST_H_ */
+
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index cd1f164..fd406ce 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -48,7 +48,8 @@ libreport_la_SOURCES = \
      user_settings.c \
      client.c \
      utf8.c \
-    event_usability.c
+    event_usability.c \
+       run_event_list.c

  libreport_la_CPPFLAGS = \
      -Wall -Wwrite-strings -Werror \
diff --git a/src/lib/run_event_list.c b/src/lib/run_event_list.c
new file mode 100644
index 0000000..559772d
--- /dev/null
+++ b/src/lib/run_event_list.c
@@ -0,0 +1,618 @@
+/*
+    Copyright (C) 2012  ABRT Team
+    Copyright (C) 2012  RedHat inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include<pthread.h>
+#include<glob.h>
+#include<regex.h>
+#include "run_event.h"
+#include "run_event_list.h"
+#include "event_usability.h"
+#include "internal_libreport.h"
+
+enum elp_process_states
+{
+    __MIN_PROC_STATE__ = 0,

__names are reserved for compiler / libc.


+
+    ELP_INIT = __MIN_PROC_STATE__,
+    ELP_START,
+    ELP_REVIEW_DATA,
+    ELP_RUN_EVENT,
+    ELP_END,
+
+    __MAX_PROC_STATE__ = ELP_END,
+};
+
+struct event_list_process
+{
+    const struct elp_signals_impl *impl;
+    const struct run_event_impl *run_impl;
+    const struct run_event_observer *run_obs;
+    const char *dump_dir_name;
+    void *args;
+
+    enum elp_process_states current;
+    const GList *events;
+    GList *internal_events;
+    GList *next;
+    GList *processed;
+
+    struct run_event_state *run_state;
+
+    res_post_run_callback post_run_callback;
+    void *post_run_param;
+    res_logging_callback logging_callback;
+    void *logging_param;
+
+    pthread_mutex_t run_mut;
+    enum elp_event_run_status last_run;
+
+    struct elp_configuration_issue last_configuration_issue;
+};
+
+void event_list_process_impl_init(struct elp_signals_impl *impl)
+{
+    memset(impl, 0, sizeof(*impl));
+}
+
+struct event_list_process *new_event_list_process(const GList *events,
+                                                  const struct 
elp_signals_impl *impl,
+                                                  const struct run_event_impl 
*run_impl,
+                                                  const struct 
run_event_observer *run_obs,
+                                                  const char *dump_dir_name,
+                                                  void *signal_args)
+{
+    assert(impl || !"NULL argument");
+    assert(run_impl || !"NULL argument");
+
+    struct event_list_process *process = xmalloc(sizeof(*process));
+
+    process->impl = impl;
+    process->run_impl = run_impl;
+    process->run_obs = run_obs;
+    process->dump_dir_name = dump_dir_name;
+    process->args = signal_args;
+    process->current = __MIN_PROC_STATE__;
+    process->events = events;
+    process->next = NULL;
+    process->internal_events = NULL;
+    process->processed = NULL;
+    process->run_state = NULL;
+
+    pthread_mutex_init(&(process->run_mut), NULL);
+
+    process->last_run = ELP_ERS_NONE;
+
+    process->post_run_callback = NULL;
+    process->post_run_param = NULL;
+    process->logging_callback = NULL;
+    process->logging_param = NULL;
+
+    return process;
+}
+
+void free_event_list_process(struct event_list_process *process)
+{
+    assert(process || !"NULL argument");
+
+    g_list_free(process->internal_events);
+
+    pthread_mutex_destroy(&(process->run_mut));
+
+    free(process);
+}
+
+const char* elp_get_current_event(const struct event_list_process *process)
+{
+    assert(process || !"NULL argument");
+
+    return process->processed ? process->processed->data : NULL;
+}
+
+void *elp_get_signal_args(const struct event_list_process *process)
+{
+    assert(process || !"NULL argument");
+
+    return process->args;
+}
+
+enum elp_event_run_status elp_get_last_event_status(const struct 
event_list_process *process)
+{
+    assert(process || !"NULL argument");
+
+    return process->last_run;
+}
+
+void elp_kill_run(struct event_list_process *process)
+{
+    assert(process || !"NULL argument");
+
+    pthread_mutex_lock(&(process->run_mut));
+
+    if (process->run_state)
+        run_event_state_kill_command(process->run_state);
+
+    pthread_mutex_unlock(&(process->run_mut));
+}
+
+void elp_set_post_run_callback(struct event_list_process *process,
+                               res_post_run_callback post_run_callback,
+                               void *post_run_param)
+{
+    assert(process || !"NULL argument");
+
+    pthread_mutex_lock(&(process->run_mut));
+
+    process->post_run_callback = post_run_callback;
+    process->post_run_param = post_run_param;
+
+    pthread_mutex_unlock(&(process->run_mut));
+}
+
+void elp_set_logging_callback(struct event_list_process *process,
+                              res_logging_callback logging_callback,
+                              void *logging_param)
+{
+    assert(process || !"NULL argument");
+
+    pthread_mutex_lock(&(process->run_mut));
+
+    process->logging_callback = logging_callback;
+    process->logging_param = logging_param;
+
+    pthread_mutex_unlock(&(process->run_mut));
+}
+
+const struct elp_configuration_issue *elp_get_last_configuration_issue(const 
struct event_list_process *process)
+{
+    return&(process->last_configuration_issue);
+}
+
+static const struct run_event_impl *elp_get_run_impl(struct event_list_process 
*process)
+{
+    assert(process || !"NULL argument");
+
+    return process->run_impl;
+}
+
+static const struct run_event_observer *elp_get_run_obs(struct 
event_list_process *process)
+{
+    assert(process || !"NULL argument");
+
+    return process->run_obs;
+}
+
+static problem_data_t *elp_create_problem_data(const struct event_list_process 
*process)
+{
+
+    struct dump_dir *dd = dd_opendir(process->dump_dir_name, 0);
+    if (!dd)
+        return NULL;
+
+    problem_data_t *pd = create_problem_data_from_dump_dir(dd);
+    dd_close(dd);
+
+    return pd;
+}
+
+static bool elp_do_need_review(const struct event_list_process *process, const 
char *event_name)
+{
+    const event_config_t *const cfg = get_event_config(event_name);
+    if (cfg&&  !cfg->ec_skip_review)
+        return true;
+
+    problem_data_t *const pd = elp_create_problem_data(process);
+    if (pd)
+        return check_event_usability(cfg, pd, NULL, NULL, EUS_LOW) != EUS_GOOD;
+
+    return true;
+}
+
+static void elp_set_last_configuration_issues(struct event_list_process 
*process,
+                                              const char *event_name,
+                                              enum event_usability_status 
status,
+                                              const GList *issues)
+{
+    pthread_mutex_lock(&(process->run_mut));
+
+    process->last_configuration_issue.event_name = event_name;
+    process->last_configuration_issue.usability = status;
+    process->last_configuration_issue.issues = issues;
+
+    pthread_mutex_unlock(&(process->run_mut));
+}
+
+static enum elp_signal_ret elp_event_configuration_issue(struct 
event_list_process *process,
+                                                         const char 
*event_name,
+                                                         enum 
event_usability_status status,
+                                                         const GList *issues)
+{
+    enum elp_signal_ret ret = ELPSR_FINISH;
+
+    if (process->impl->configuration_issue)
+    {
+        elp_set_last_configuration_issues(process, event_name, status, issues);
+
+        ret = process->impl->configuration_issue(process);
+
+        elp_set_last_configuration_issues(process, NULL, EUS_GOOD, NULL);
+    }
+
+    return ret;
+}
+
+typedef enum event_usability_status (*validator_fn)(const event_config_t *, 
const  problem_data_t *,
+                                                    const GList *, GList **, 
enum event_usability_status);
+
+static enum elp_signal_ret elp_validate_event_config(struct event_list_process 
*process,
+                                                     const event_config_t *cfg,
+                                                     const char *event_name,
+                                                     const problem_data_t *pd,
+                                                     const GList 
*not_loaded_items,
+                                                     enum 
event_usability_status min_level,
+                                                     validator_fn *validators)
+{
+    enum elp_signal_ret resp = ELPSR_CONTINUE;
+
+    if (!cfg)
+        return resp;
+
+    enum event_usability_status status = EUS_GOOD;
+    validator_fn *validator = validators;
+    GList* issues = NULL;
+    while(*validator)
+    {
+        status = worst_usability(status, (*validator)(cfg, pd, 
not_loaded_items,&issues, min_level));
+        ++validator;
+    }
+
+    if (status == EUS_UNUSABLE)
+    {
+        resp = elp_event_configuration_issue(process, event_name, status, 
issues);
+        g_list_free_full(issues, (GDestroyNotify)free);
+
+        if (resp == ELPSR_CONTINUE)
+            error_msg_and_die("Cannot continue with unusable event '%s'", 
event_name);
+    }
+
+    return resp;
+}
+
+static enum elp_signal_ret elp_validate_event(struct event_list_process 
*process,
+                                              const char *event_name,
+                                              const problem_data_t *pd,
+                                              const GList *not_loaded_items,
+                                              enum event_usability_status 
min_level,
+                                              validator_fn *validators)
+{
+    return elp_validate_event_config(process, get_event_config(event_name), 
event_name, pd,
+                                     not_loaded_items, min_level, validators);
+}
+
+static const GList* elp_select_next_event(struct event_list_process *process, 
const GList **event_list, const GList *not_loaded_items, enum elp_signal_ret 
*ret)
+{
+    assert(process || !"NULL argument");
+    assert(event_list || !"NULL argument");
+
+    static validator_fn validators[] = {
+        check_event_usability,
+        NULL,
+    };
+
+    const GList *tmp;
+    tmp = *event_list;
+    *event_list = g_list_next(tmp);
+
+    problem_data_t *pd = elp_create_problem_data(process);
+    if (!pd)
+        return tmp;
+
+    while(tmp)
+    {
+        const enum elp_signal_ret resp = elp_validate_event(process, 
tmp->data, pd,
+                                                            not_loaded_items, 
EUS_UNUSABLE, validators);
+
+        if (ret)
+            *ret = resp;
+
+        if (resp == ELPSR_CONTINUE)
+            break;
+        else if (resp == ELPSR_FINISH)
+        {
+            tmp = *event_list = NULL;
+            break;
+        }
+        else if (resp != ELPSR_NEXT_EVENT)
+        {
+            assert(!"unexpected return value");
+        }
+
+        tmp = *event_list;
+        *event_list = g_list_next(tmp);
+    }
+
+    free_problem_data(pd);
+    return tmp;
+}
+
+static GList* elp_revise_event_list(struct event_list_process *process, const 
GList *event_list)
+{
+    GList *revised_list = NULL;
+    GList *created_items = NULL;
+    enum elp_signal_ret ret;
+
+    const GList *event;
+    while ((event = elp_select_next_event(process,&event_list, 
created_items,&ret)))
+    {
+        const event_config_t *const cfg = get_event_config(event->data);
+        if (cfg&&  cfg->ec_creates_items)
+        {
+            /* have to create a copy because of threads */
+            /* TODO : find a better place for following lines */
+            char *item_list = xstrdup(cfg->ec_creates_items);
+            char *bck = item_list;
+            while (item_list[0])
+            {
+                char *end = strchr(item_list, ',');
+                if (end) *end = '\0';
+                created_items = g_list_prepend(created_items, 
xstrdup(item_list));
+                if (!end)
+                    break;
+                item_list = end + 1;
+            }
+            free(bck);
+        }
+
+        revised_list = g_list_prepend(revised_list, event->data);
+    }
+
+    g_list_free_full(created_items, (GDestroyNotify)free);
+
+    if (ret != ELPSR_FINISH)
+        return g_list_reverse(revised_list);
+
+    g_list_free(revised_list);
+    return NULL;
+}
+
+static GList *elp_next_event(struct event_list_process *process)
+{
+    assert(process || !"NULL argument");
+
+    return (GList *)elp_select_next_event(process, (const GList 
**)&process->next, NULL, NULL);
+}
+
+static bool event_list_process_call(struct event_list_process *process,
+                                    elp_signal cb,
+                                    enum elp_process_states ok_state,
+                                    enum elp_signal_ret default_ret)
+{
+    assert(process || !"NULL argument");
+    assert((ok_state>= __MIN_PROC_STATE__&&  ok_state<= __MAX_PROC_STATE__) || 
!"out of range argument");
+
+    const enum elp_signal_ret ret = cb ? cb(process) : default_ret;
+
+    switch (ret)
+    {
+        case ELPSR_CONTINUE:
+            process->current = ok_state;
+            break;
+        case ELPSR_NEXT_EVENT:
+            process->current = ELP_START;
+            break;
+        case ELPSR_FINISH:
+            process->current = ELP_END;
+            break;
+        default:
+            assert(!"unexpected signal return value");
+            error_msg_and_die("unexpected signal return value %d", ret);
+            break;
+    }
+
+    return ret == ELPSR_CONTINUE;
+}
+
+struct process_run_event_watcher
+{
+    const struct run_event_observer *wrapped_obs;
+    bool failed;
+    bool stopper;
+};
+
+static void process_command_started(pid_t pid, void *args)
+{
+    struct process_run_event_watcher *pre = (struct process_run_event_watcher 
*)args;
+
+    if (pre->wrapped_obs&&  pre->wrapped_obs->command_started)
+        pre->wrapped_obs->command_started(pid, pre->wrapped_obs->args);
+}
+
+static void process_command_msg_processed(const char *msg, const char 
*raw_input, const char *rsp, void *args)
+{
+    struct process_run_event_watcher *pre = (struct process_run_event_watcher 
*)args;
+
+    /* TODO : should I move it to client.h ? */
+    if (!pre->stopper)
+        pre->stopper = !strncmp(msg, "THANK_YOU", sizeof("THANK_YOU") -1);
+
+    if (pre->wrapped_obs&&  pre->wrapped_obs->command_msg_processed)
+        pre->wrapped_obs->command_msg_processed(msg, raw_input, rsp, 
pre->wrapped_obs->args);
+}
+
+static void process_command_finished(int retval, int status, const char 
*err_msg, void *args)
+{
+    struct process_run_event_watcher *pre = (struct process_run_event_watcher 
*)args;
+
+    pre->failed = retval != 0;
+
+    if (pre->wrapped_obs&&  pre->wrapped_obs->command_finished)
+        pre->wrapped_obs->command_finished(retval, status, err_msg, 
pre->wrapped_obs->args);
+}
+
+int elp_next_step(struct event_list_process *process)
+{
+    /* before process start, revise event list and remove not configured and */
+    /* unusable events */
+    if (process->current == ELP_INIT)
+    {
+        process->current = ELP_START;
+
+        /* create internal event list from origin event list */
+        /* it is a copy of original list without unusable events */
+        process->internal_events = process->next = elp_revise_event_list(process, 
process->events);
+    }
+
+    /* Process all event from list until reaches event that needs review, 
event run failure */
+    /* or the end of the event list */
+    while (1)
+    {
+        if (process->current == ELP_START)
+        {
+            /* selects next event from internal list */
+            process->processed = elp_next_event(process);
+
+            if (!process->processed)
+            {   /* Event list is empty now */
+                process->current = ELP_END;
+            }
+            else
+            {
+                /* If callback next_event_selected is not set the process 
expects that */
+                /* there is no problem to continue thus default response is 
CONTINUE */
+                /* It callback returns a positive response process state is 
set to START */
+                if (!event_list_process_call(process, 
process->impl->next_event_selected, ELP_START, ELPSR_CONTINUE))
+                    return true;
+
+                if (elp_do_need_review(process, 
elp_get_current_event(process)))
+                    process->current = ELP_REVIEW_DATA;
+                else
+                    process->current = ELP_RUN_EVENT;
+            }
+
+            /* return is not here because we want to continue with next state 
*/
+            /* use case : next_step with start state causes beginning to 
review */
+            /*            or immediate run of event commands */
+        }
+
+        if (process->current == ELP_REVIEW_DATA)
+        {
+            /* review_data signal has high priority thus if call back is not 
set, */
+            /* then we expect that data are not reviewed and event is skipped 
*/
+
+            /* return pauses the processing of events because process has to 
wait on next */
+            /* step signaling that review is finished, thus return if positive 
answer */
+            /* was returned from review_data callback */
+
+            /* if negative answer was returned we want to select next event 
immediately */
+            /* or finish the process */
+            if(event_list_process_call(process, process->impl->review_data, 
ELP_RUN_EVENT, ELPSR_NEXT_EVENT))
+                return true;
+        }
+
+        if (process->current == ELP_RUN_EVENT)
+        {
+            /* If callback run_event is not set the process expects that */
+            /* there is no problem to continue thus default response is 
CONTINUE */
+
+            /* if negative answer was returned we want to select next event 
immediately */
+            /* or finish the process */
+            if (!event_list_process_call(process, process->impl->run_event, 
ELP_RUN_EVENT, ELPSR_CONTINUE))
+                return true;
+
+            const char *event_name = elp_get_current_event(process);
+
+            struct process_run_event_watcher process_watcher = {
+                .failed = false,
+                .stopper = false,
+            };
+
+            process_watcher.wrapped_obs = elp_get_run_obs(process);
+
+            struct run_event_observer process_obs = {
+                .command_started = process_command_started,
+                .command_msg_processed = process_command_msg_processed,
+                .command_finished = process_command_finished,
+            };
+
+            process_obs.args =&process_watcher;
+
+            const char *dump_dir_name = process->dump_dir_name;
+
+            pthread_mutex_lock(&(process->run_mut));
+
+            struct run_event_state *run_state = new_run_event_state();
+            process->run_state = run_state;
+            run_state->post_run_callback = process->post_run_callback;
+            run_state->post_run_param = process->post_run_param;
+            run_state->logging_callback = process->logging_callback;
+            run_state->logging_param = process->logging_param;
+
+            pthread_mutex_unlock(&(process->run_mut));
+
+            prepare_commands(run_state, dump_dir_name, event_name);
+            run_event_state_on_dir_name(run_state, dump_dir_name, event_name,
+                                        
elp_get_run_impl(process),&process_obs);
+
+            /* take care about stopper occurrence only if event was successful 
*/
+            /* thus default value is not stopper occurrence */
+            bool stopper = false;
+
+            process->last_run = ELP_ERS_FAILED;
+            if (!process_watcher.failed)
+            {
+                if (run_state->children_count == 0)
+                {
+                    process->last_run = ELP_ERS_NOT_FOUND;
+
+                    /* run_event do not provide any callback for not event 
found notification */
+                    /* and no event is considered as fail thus setting failed 
var to TRUE */
+                    process_watcher.failed = true;
+                }
+                else
+                {
+                    process->last_run = ELP_ERS_SUCCESSFUL;
+                    stopper = process_watcher.stopper;
+                }
+            }
+
+            /* stopper means that event decided to stop all further processing 
the */
+            /* thus successful state is ELP_END and default response is 
ELPSR_FINISH */
+            event_list_process_call(process, process->impl->event_done,
+                                    stopper ? ELP_END : ELP_START,
+                                    stopper ? ELPSR_FINISH : ELPSR_CONTINUE);
+
+            pthread_mutex_lock(&(process->run_mut));
+            free_run_event_state(run_state);
+            process->run_state = NULL;
+            pthread_mutex_unlock(&(process->run_mut));
+
+            /* do not forward to next step if event failed */
+            if (process_watcher.failed)
+                return true;
+        }
+
+        if (process->current == ELP_END)
+        {
+            /* Don't care about result, result can't change anything */
+            event_list_process_call(process, process->impl->finished, ELP_END, 
ELPSR_FINISH);
+            return false;
+        }
+    }
+
+    assert(!"cannot get here");
+    return false;
+}

Before these patches:

# grep -r thread .
./src/gui-wizard-gtk/Makefile.am:# -lgthread-2.0
./src/lib/json.c:#include <btparser/thread.h>
./src/lib/json.c:    struct btp_thread *core_bt = 
btp_load_core_backtrace(pd_item);
./src/lib/json.c:        ureport_add_int(item, "thread", 0);
./src/lib/json.c:    btp_thread_free(core_bt);
./src/lib/json.c:    * ureport_add_item_int(ureport, pd, "crash_thread", NULL);
./src/lib/json.c:    ureport_add_int(ureport, "crash_thread", 0);
./src/plugins/rhbz.c:#include <btparser/thread.h>
./src/plugins/rhbz.c: *     - otherwise preview of crashed thread stack trace 
is created
./src/plugins/rhbz.c:        /* Get optimized thread stack trace for 10 top 
most frames */
./src/plugins/rhbz.c:        struct btp_thread *thread = 
btp_backtrace_get_optimized_thread(backtrace, 10);
./src/plugins/rhbz.c:        if (!thread)
./src/plugins/rhbz.c:            log(_("Can't find crash thread"));
./src/plugins/rhbz.c:        btp_thread_append_to_str(thread, bt, true);
./src/plugins/rhbz.c:        btp_thread_free(thread);


After these patches:

# grep -r thread .
./libreport.spec.in:%{_includedir}/libreport/run_event_list_thread.h
./src/gui-wizard-gtk/wizard.c:#include "run_event_list_thread.h"
./src/gui-wizard-gtk/wizard.c:static pthread_t g_gui_thread_id;
./src/gui-wizard-gtk/wizard.c:        gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:        gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    show_error_as_msgbox_mts(msg, 
!pthread_equal(g_gui_thread_id, pthread_self()));
./src/gui-wizard-gtk/wizard.c:static void process_step_done_callback_fn(struct 
elp_thread_args *args)
./src/gui-wizard-gtk/wizard.c:static void process_start_callback_fn(struct 
elp_thread_args *args)
./src/gui-wizard-gtk/wizard.c:        gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:        gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:static void process_finish_callback_fn(struct 
elp_thread_args  *args)
./src/gui-wizard-gtk/wizard.c:    
free_event_list_process(elp_thread_args_get_process(args));
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:        
elp_thread_loop_kill_command(g_event_process);
./src/gui-wizard-gtk/wizard.c:    if (g_reviewing_data || 
!elp_thread_is_runnig(g_event_process))
./src/gui-wizard-gtk/wizard.c:        
elp_thread_loop_next_step(g_event_process);
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:        gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:        gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    elp_thread_run(g_event_process, proc);
./src/gui-wizard-gtk/wizard.c:        
elp_thread_loop_next_step(g_event_process);
./src/gui-wizard-gtk/wizard.c:    gdk_threads_enter();
./src/gui-wizard-gtk/wizard.c:    gdk_threads_leave();
./src/gui-wizard-gtk/wizard.c:    elp_thread_loop_next_step(g_event_process);
./src/gui-wizard-gtk/wizard.c:    
elp_thread_args_set_on_step_done(g_event_process, 
process_step_done_callback_fn);
./src/gui-wizard-gtk/wizard.c:    elp_thread_args_set_on_start(g_event_process, 
process_start_callback_fn);
./src/gui-wizard-gtk/wizard.c:    
elp_thread_args_set_on_finish(g_event_process, process_finish_callback_fn);
./src/gui-wizard-gtk/wizard.c:    g_gui_thread_id = pthread_self();
./src/gui-wizard-gtk/wizard.c:        
g_source_attach((GSource*)gtk_assistant_source, 
g_main_context_get_thread_default());
./src/gui-wizard-gtk/main.c:#include "run_event_list_thread.h"
./src/gui-wizard-gtk/main.c:struct elp_thread_args *g_event_process;
./src/gui-wizard-gtk/main.c:    g_event_process = new_elp_thread_args();
./src/gui-wizard-gtk/main.c:    gdk_threads_init ();
./src/gui-wizard-gtk/main.c:    gdk_threads_enter ();
./src/gui-wizard-gtk/main.c:    if (elp_thread_init(g_event_process))
./src/gui-wizard-gtk/main.c:        perror_msg_and_die("initializatoin of event 
process thread failed");
./src/gui-wizard-gtk/main.c:    gdk_threads_leave();
./src/gui-wizard-gtk/main.c:    free_elp_thread_args(g_event_process);
./src/gui-wizard-gtk/wizard.h:struct elp_thread_args;
./src/gui-wizard-gtk/wizard.h:extern struct elp_thread_args *g_event_process;
./src/gui-wizard-gtk/Makefile.am:# -lgthread-2.0
./src/include/run_event_list_thread.h: * struct elp_thread_args *thread_proc = 
new_elp_thread_args();
./src/include/run_event_list_thread.h: * if (elp_thread_init(thread_proc))
./src/include/run_event_list_thread.h: * elp_thread_run(thread_proc, 
event_proc);
./src/include/run_event_list_thread.h: * elp_thread_loop_next_step(thread_proc);
./src/include/run_event_list_thread.h: * 
free_event_list_process(elp_thread_get_process(thread_proc));
./src/include/run_event_list_thread.h: * free_elp_thread(thread_proc);
./src/include/run_event_list_thread.h: * Structure that holds state of thread 
process.
./src/include/run_event_list_thread.h:struct elp_thread_args;
./src/include/run_event_list_thread.h: * Callback used by thread process to 
send signals about process state
./src/include/run_event_list_thread.h:typedef void(* 
elp_thread_args_callback)(struct elp_thread_args *args);
./src/include/run_event_list_thread.h: * Creates a new thread process state
./src/include/run_event_list_thread.h:struct elp_thread_args 
*new_elp_thread_args();
./src/include/run_event_list_thread.h: * @param args Not NULL pointer to thread 
process state
./src/include/run_event_list_thread.h:void elp_thread_args_set_on_start(struct 
elp_thread_args *args,
./src/include/run_event_list_thread.h:                                  
elp_thread_args_callback cb);
./src/include/run_event_list_thread.h: * @param args Not NULL pointer to thread 
process state
./src/include/run_event_list_thread.h:void 
elp_thread_args_set_on_step_done(struct elp_thread_args *args,
./src/include/run_event_list_thread.h:                                      
elp_thread_args_callback cb);
./src/include/run_event_list_thread.h: * @param args Not NULL pointer to thread 
process state
./src/include/run_event_list_thread.h:void elp_thread_args_set_on_finish(struct 
elp_thread_args *args,
./src/include/run_event_list_thread.h:                                   
elp_thread_args_callback cb);
./src/include/run_event_list_thread.h: * @param args Not NULL pointer to thread 
process state
./src/include/run_event_list_thread.h:struct event_list_process 
*elp_thread_args_get_process(const struct elp_thread_args *args);
./src/include/run_event_list_thread.h: * Destroy thread process
./src/include/run_event_list_thread.h: * @param args A pointer to thread process
./src/include/run_event_list_thread.h:void free_elp_thread_args(struct 
elp_thread_args *args);
./src/include/run_event_list_thread.h: * Creates a thread used by a process
./src/include/run_event_list_thread.h: * @param args Not NULL pointer to thread 
process state
./src/include/run_event_list_thread.h:int elp_thread_init(struct 
elp_thread_args *args);
./src/include/run_event_list_thread.h: * Interrupts an event list process and 
kills a process thread.
./src/include/run_event_list_thread.h: * A thread process cannot be used after 
this function call.
./src/include/run_event_list_thread.h: * @param args Not NULL pointer to thread 
process state
./src/include/run_event_list_thread.h:void elp_thread_kill(struct 
elp_thread_args *args);
./src/include/run_event_list_thread.h: * Interrupts an event list process and 
leaves a process thread untouched.
./src/include/run_event_list_thread.h: * @param args Not NULL pointer to thread 
process state
./src/include/run_event_list_thread.h:void elp_thread_interrupt(struct 
elp_thread_args *args);
./src/include/run_event_list_thread.h: * @param args Not NULL pointer to thread 
process state
./src/include/run_event_list_thread.h:void elp_thread_run(struct 
elp_thread_args *args, struct event_list_process *process);
./src/include/run_event_list_thread.h: * @param args Not NULL pointer to thread 
process state
./src/include/run_event_list_thread.h:int elp_thread_is_runnig(struct 
elp_thread_args *args);
./src/include/run_event_list_thread.h: * Notify a thread process to perform 
next event list process step.
./src/include/run_event_list_thread.h: * @param args Not NULL pointer to thread 
process state
./src/include/run_event_list_thread.h:void elp_thread_loop_next_step(struct 
elp_thread_args *args);
./src/include/run_event_list_thread.h: * @param args Not NULL pointer to thread 
process state
./src/include/run_event_list_thread.h:void elp_thread_loop_kill_command(struct 
elp_thread_args *args);
./src/include/Makefile.am:    run_event_list_thread.h
./src/lib/run_event_list.c:#include <pthread.h>
./src/lib/run_event_list.c:    pthread_mutex_t run_mut;
./src/lib/run_event_list.c:    pthread_mutex_init(&(process->run_mut), NULL);
./src/lib/run_event_list.c:    pthread_mutex_destroy(&(process->run_mut));
./src/lib/run_event_list.c:    pthread_mutex_lock(&(process->run_mut));
./src/lib/run_event_list.c:    pthread_mutex_unlock(&(process->run_mut));
./src/lib/run_event_list.c:    pthread_mutex_lock(&(process->run_mut));
./src/lib/run_event_list.c:    pthread_mutex_unlock(&(process->run_mut));
./src/lib/run_event_list.c:    pthread_mutex_lock(&(process->run_mut));
./src/lib/run_event_list.c:    pthread_mutex_unlock(&(process->run_mut));
./src/lib/run_event_list.c:    pthread_mutex_lock(&(process->run_mut));
./src/lib/run_event_list.c:    pthread_mutex_unlock(&(process->run_mut));
./src/lib/run_event_list.c:            /* have to create a copy because of 
threads */
./src/lib/run_event_list.c:            pthread_mutex_lock(&(process->run_mut));
./src/lib/run_event_list.c:            
pthread_mutex_unlock(&(process->run_mut));
./src/lib/run_event_list.c:            pthread_mutex_lock(&(process->run_mut));
./src/lib/run_event_list.c:            
pthread_mutex_unlock(&(process->run_mut));
./src/lib/run_event_list_thread.c:#include <pthread.h>
./src/lib/run_event_list_thread.c:#include "run_event_list_thread.h"
./src/lib/run_event_list_thread.c:struct elp_thread_args
./src/lib/run_event_list_thread.c:    pthread_t process_tid;
./src/lib/run_event_list_thread.c:    pthread_mutex_t sync_mut;
./src/lib/run_event_list_thread.c:    pthread_cond_t proc_cond;
./src/lib/run_event_list_thread.c:    pthread_cond_t step_cond;
./src/lib/run_event_list_thread.c:    elp_thread_args_callback start_cb;
./src/lib/run_event_list_thread.c:    elp_thread_args_callback step_done_cb;
./src/lib/run_event_list_thread.c:    elp_thread_args_callback finish_cb;
./src/lib/run_event_list_thread.c:struct elp_thread_args *new_elp_thread_args()
./src/lib/run_event_list_thread.c:    struct elp_thread_args *args = 
xzalloc(sizeof(*args));
./src/lib/run_event_list_thread.c:    pthread_mutex_init(&(args->sync_mut), 
NULL);
./src/lib/run_event_list_thread.c:    pthread_cond_init(&(args->proc_cond), 
NULL);
./src/lib/run_event_list_thread.c:    pthread_cond_init(&(args->step_cond), 
NULL);
./src/lib/run_event_list_thread.c:void elp_thread_args_set_on_start(struct 
elp_thread_args *args,
./src/lib/run_event_list_thread.c:                                  
elp_thread_args_callback cb)
./src/lib/run_event_list_thread.c:void elp_thread_args_set_on_step_done(struct 
elp_thread_args *args,
./src/lib/run_event_list_thread.c:                                      
elp_thread_args_callback cb)
./src/lib/run_event_list_thread.c:void elp_thread_args_set_on_finish(struct 
elp_thread_args *args,
./src/lib/run_event_list_thread.c:                                   
elp_thread_args_callback cb)
./src/lib/run_event_list_thread.c:static void 
elp_thread_args_set_process(struct elp_thread_args *args,
./src/lib/run_event_list_thread.c:struct event_list_process 
*elp_thread_args_get_process(const struct elp_thread_args *args)
./src/lib/run_event_list_thread.c:static void elp_thread_args_on_start(struct 
elp_thread_args *args)
./src/lib/run_event_list_thread.c:static void 
elp_thread_args_on_step_done(struct elp_thread_args *args)
./src/lib/run_event_list_thread.c:static void elp_thread_args_on_finish(struct 
elp_thread_args *args)
./src/lib/run_event_list_thread.c:void elp_thread_interrupt_internal(struct 
elp_thread_args *args)
./src/lib/run_event_list_thread.c:static void elp_thread_kill_internal(struct 
elp_thread_args *args)
./src/lib/run_event_list_thread.c:    elp_thread_interrupt_internal(args);
./src/lib/run_event_list_thread.c:static int elp_thread_wait_on_process(struct 
elp_thread_args *args)
./src/lib/run_event_list_thread.c:    pthread_mutex_lock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:        const int error = 
pthread_cond_wait(&(args->proc_cond), &(args->sync_mut));
./src/lib/run_event_list_thread.c:            elp_thread_kill_internal(args);
./src/lib/run_event_list_thread.c:    pthread_mutex_unlock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:static int elp_thread_wait_on_step(struct 
elp_thread_args *args)
./src/lib/run_event_list_thread.c:    pthread_mutex_lock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:        const int error = 
pthread_cond_wait(&(args->step_cond), &(args->sync_mut));
./src/lib/run_event_list_thread.c:            elp_thread_kill_internal(args);
./src/lib/run_event_list_thread.c:    pthread_mutex_unlock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:void free_elp_thread_args(struct 
elp_thread_args *args)
./src/lib/run_event_list_thread.c:    pthread_cond_destroy(&(args->step_cond));
./src/lib/run_event_list_thread.c:    pthread_cond_destroy(&(args->proc_cond));
./src/lib/run_event_list_thread.c:    pthread_mutex_destroy(&(args->sync_mut));
./src/lib/run_event_list_thread.c:void elp_thread_run(struct elp_thread_args 
*args, struct event_list_process *process)
./src/lib/run_event_list_thread.c:    pthread_mutex_lock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:    if (elp_thread_is_runnig(args))
./src/lib/run_event_list_thread.c:        error_msg_and_die("event list process 
thread is already runnig");
./src/lib/run_event_list_thread.c:    elp_thread_args_set_process(args, 
process);
./src/lib/run_event_list_thread.c:    pthread_cond_signal(&(args->proc_cond));
./src/lib/run_event_list_thread.c:    pthread_mutex_unlock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:int elp_thread_is_runnig(struct 
elp_thread_args *args)
./src/lib/run_event_list_thread.c:void elp_thread_loop_next_step(struct 
elp_thread_args *args)
./src/lib/run_event_list_thread.c:    pthread_mutex_lock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:    pthread_cond_signal(&(args->step_cond));
./src/lib/run_event_list_thread.c:    pthread_mutex_unlock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:static void *elp_thread(void *args)
./src/lib/run_event_list_thread.c:    struct elp_thread_args *p = (struct 
elp_thread_args *)args;
./src/lib/run_event_list_thread.c:    while (elp_thread_wait_on_process(p))
./src/lib/run_event_list_thread.c:        elp_thread_args_on_start(p);
./src/lib/run_event_list_thread.c:        pthread_mutex_lock(&(p->sync_mut));
./src/lib/run_event_list_thread.c:            
pthread_mutex_unlock(&(p->sync_mut));
./src/lib/run_event_list_thread.c:            elp_thread_wait_on_step(p);
./src/lib/run_event_list_thread.c:            while (elp_thread_wait_on_step(p) 
&& cont)
./src/lib/run_event_list_thread.c:                
elp_thread_args_on_step_done(p);
./src/lib/run_event_list_thread.c:            
pthread_mutex_lock(&(p->sync_mut));
./src/lib/run_event_list_thread.c:        pthread_mutex_unlock(&(p->sync_mut));
./src/lib/run_event_list_thread.c:        elp_thread_args_on_finish(p);
./src/lib/run_event_list_thread.c:int elp_thread_init(struct elp_thread_args 
*args)
./src/lib/run_event_list_thread.c:    return 
pthread_create(&(args->process_tid), NULL, elp_thread, args);
./src/lib/run_event_list_thread.c:void elp_thread_loop_kill_command(struct 
elp_thread_args *args)
./src/lib/run_event_list_thread.c:    pthread_mutex_lock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:    pthread_mutex_unlock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:void elp_thread_interrupt(struct 
elp_thread_args *args)
./src/lib/run_event_list_thread.c:    pthread_mutex_lock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:    elp_thread_interrupt_internal(args);
./src/lib/run_event_list_thread.c:    pthread_cond_signal(&(args->step_cond));
./src/lib/run_event_list_thread.c:    pthread_mutex_unlock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:void elp_thread_kill(struct elp_thread_args 
*args)
./src/lib/run_event_list_thread.c:    pthread_mutex_lock(&(args->sync_mut));
./src/lib/run_event_list_thread.c:    elp_thread_kill_internal(args);
./src/lib/run_event_list_thread.c:    pthread_cond_signal(&(args->proc_cond));
./src/lib/run_event_list_thread.c:    pthread_mutex_unlock(&(args->sync_mut));
./src/lib/json.c:#include <btparser/thread.h>
./src/lib/json.c:    struct btp_thread *core_bt = 
btp_load_core_backtrace(pd_item);
./src/lib/json.c:        ureport_add_int(item, "thread", 0);
./src/lib/json.c:    btp_thread_free(core_bt);
./src/lib/json.c:    * ureport_add_item_int(ureport, pd, "crash_thread", NULL);
./src/lib/json.c:    ureport_add_int(ureport, "crash_thread", 0);
./src/lib/Makefile.am:  run_event_list_thread.c
./src/plugins/rhbz.c:#include <btparser/thread.h>
./src/plugins/rhbz.c: *     - otherwise preview of crashed thread stack trace 
is created
./src/plugins/rhbz.c:        /* Get optimized thread stack trace for 10 top 
most frames */
./src/plugins/rhbz.c:        struct btp_thread *thread = 
btp_backtrace_get_optimized_thread(backtrace, 10);
./src/plugins/rhbz.c:        if (!thread)
./src/plugins/rhbz.c:            log(_("Can't find crash thread"));
./src/plugins/rhbz.c:        btp_thread_append_to_str(thread, bt, true);
./src/plugins/rhbz.c:        btp_thread_free(thread);


I don't think this is an improvement.
Who will debug the next nightmage threading bug?

--
vda

Reply via email to