struct sr_core_stacktrace * sr_core_stacktrace_from_json(struct sr_json_value *root, char **error_message) { if (!JSON_CHECK_TYPE(root, SR_JSON_OBJECT, "stacktrace")) return NULL; struct sr_core_stacktrace *result = sr_core_stacktrace_new(); bool success = JSON_READ_UINT16(root, "signal", &result->signal) && JSON_READ_STRING(root, "executable", &result->executable) && JSON_READ_BOOL(root, "only_crash_thread", &result->only_crash_thread); if (!success) goto fail; /* Read threads. */ struct sr_json_value *stacktrace = json_element(root, "stacktrace"); if (stacktrace) { if (!JSON_CHECK_TYPE(stacktrace, SR_JSON_ARRAY, "stacktrace")) goto fail; struct sr_json_value *json_thread; FOR_JSON_ARRAY(stacktrace, json_thread) { struct sr_core_thread *thread = sr_core_thread_from_json(json_thread, error_message); if (!thread) goto fail; struct sr_json_value *crash_thread = json_element(json_thread, "crash_thread"); if (crash_thread) { if (!JSON_CHECK_TYPE(crash_thread, SR_JSON_BOOLEAN, "crash_thread")) { sr_core_thread_free(thread); goto fail; } if (crash_thread->u.boolean) result->crash_thread = thread; } result->threads = sr_core_thread_append(result->threads, thread); } } return result; fail: sr_core_stacktrace_free(result); return NULL; }
/* destructor */ void sr_py_core_thread_free(PyObject *object) { struct sr_py_core_thread *this = (struct sr_py_core_thread *)object; /* the list will decref all of its elements */ Py_DECREF(this->frames); this->thread->frames = NULL; sr_core_thread_free(this->thread); PyObject_Del(object); }
static int unwind_thread(Dwfl_Thread *thread, void *data) { struct thread_callback_arg *thread_arg = data; char **error_msg = &thread_arg->error_msg; struct sr_core_thread *result = sr_core_thread_new(); if (!result) { set_error("Failed to initialize stacktrace memory"); return DWARF_CB_ABORT; } result->id = (int64_t)dwfl_thread_tid(thread); struct frame_callback_arg frame_arg = { .thread = result, .error_msg = NULL }; int ret = dwfl_thread_getframes(thread, frame_callback, &frame_arg); if (ret == -1) { warn("dwfl_thread_getframes failed for thread id %d: %s", (int)result->id, dwfl_errmsg(-1)); } else if (ret == DWARF_CB_ABORT) { *error_msg = frame_arg.error_msg; goto abort; } else if (ret != 0 && ret != CB_STOP_UNWIND) { *error_msg = sr_strdup("Unknown error in dwfl_thread_getframes"); goto abort; } if (!error_msg && !frame_arg.thread->frames) { set_error("No frames found for thread id %d", (int)result->id); goto abort; } thread_arg->stacktrace->threads = sr_core_thread_append(thread_arg->stacktrace->threads, result); return DWARF_CB_OK; abort: sr_core_thread_free(result); return DWARF_CB_ABORT; }
void sr_core_stacktrace_free(struct sr_core_stacktrace *stacktrace) { if (!stacktrace) return; while (stacktrace->threads) { struct sr_core_thread *thread = stacktrace->threads; stacktrace->threads = thread->next; sr_core_thread_free(thread); } free(stacktrace); }