This patch contains changes requested by Eli and Tom, and includes documentation for the new features. > Instead of evregpy_get_nlisteners checking the list size, I think it > would be better to have "evregpy_any_listeners_p" return a boolean, and > then check whether the list is empty. This may be more efficient and is > what you want to do anyhow. > How about evregpy_no_listeners_p ? Fits better with the way the code was written. > Sami> +event_object * > Sami> +create_event_object (PyTypeObject *py_type) > Sami> +{ > Sami> + event_object *event_obj; > Sami> + > Sami> + event_obj = PyObject_New (event_object, py_type); > Sami> + if (!event_obj) > Sami> + goto fail; > Sami> + > Sami> + event_obj->dict = PyDict_New (); > Sami> + if (!event_obj->dict) > Sami> + goto fail; > Sami> + > Sami> + return event_obj; > Sami> + > Sami> + fail: > Sami> + Py_XDECREF (event_obj); > Sami> + Py_XDECREF (event_obj->dict); > > Won't decrefing event_obj automatically free the dict when needed? > I didn't look closely but maybe other create_* functions have this issue. > I fixed all the create_* functions and made sure the dealloc functions are using Py_XDECREF. > Sami> +static int > Sami> +add_new_registry (eventregistry_object **registryp, char *name) > Sami> +{ > Sami> + *registryp = create_eventregistry_object (); > Sami> + if(*registryp == NULL) > > Newline between these lines. > Space before open paren. > > Why not just return the new registry, or NULL on error? > That would be simpler. > Adding the registry, and doing the needed error checking here, makes the calling code simpler. The calling code is what will be extended in future development. > > Sami> +static void > Sami> +python_inferior_exit (struct inferior *inf) > Sami> +{ > Sami> + struct cleanup *cleanup; > Sami> + LONGEST exitcode_val; > Sami> + LONGEST *exit_code; > Sami> + > Sami> + cleanup = ensure_python_env (get_current_arch (), current_language); > Sami> + > Sami> + if (get_internalvar_integer (lookup_internalvar ("_exitcode"),&exitcode_val)) > Sami> + exit_code =&exitcode_val; > Sami> + > Sami> + if (exit_code > Sami> +&& emit_exited_event (exit_code)< 0) > > You have to initialize exit_code to NULL for this to work properly. > Done. > However, I think this is pretty ugly. > It seems like there should be a better way to get this than looking up > a convenience variable. > Hmm I looked through the code to find another way but could not. handle_inferior_event which sets the convenience variable uses execution_control_state which I don't have access to. > I think we need an event representing a thread exit. > It is ok by me if this comes in a separate patch. > (FWIW I have a few new events on my branch; I'll update those once this > patch goes in.) > In the original patch this event was halfway between thread exit and inferior exit. So I decided to make it inferior exit with the intention on adding thread exited/created events in a future patch. > Sami> + signal_event_obj->stop_signal = > Sami> + (PyStringObject *) PyString_FromString (stop_signal); > > It is more usual to just use PyObject* everywhere, and not cast to the > more specific types. > > This change should let you eliminate other casts in the patch. > Done. I also, updated breakpoint_event_object. I was going with the oposite mindset of keeping the type information until a cast is required. > Sami> +stop_event_object * > Sami> +create_stop_event_object (PyTypeObject *py_type, thread_object *thread) > Sami> +{ > Sami> + stop_event_object *stop_event_obj = > Sami> + (stop_event_object *) create_event_object (py_type); > Sami> + > Sami> + if (!stop_event_obj) > Sami> + goto fail; > Sami> + > Sami> + stop_event_obj->inferior_thread = (PyObject *) thread; > Sami> + > Sami> + if (evpy_add_attribute ((event_object *) stop_event_obj, > Sami> + "inferior_thread", > Sami> + stop_event_obj->inferior_thread)< 0) > Sami> + goto fail; > Sami> + > Sami> + > Sami> + return stop_event_obj; > > I think it would be better to just have one cast at the end, instead of > lots of casts in the body. > Hmm if I change stop_event_object* to event_object it would eliminate two casts but also add two. One when setting the inferior thread and one for returning. Same goes for all the create_* functions or should I change all of those to return more generic objects ? > Sami> + if (bs&& bs->breakpoint_at > Sami> +&& bs->breakpoint_at->type == bp_breakpoint) > Sami> + { > Sami> + if (evregpy_get_nlisteners (gdb_py_events.breakpoint) == 0) > Sami> + return 0; > > I think the short-circuiting logic should be hoisted to the top of the > function. This is more efficient and also lets you avoid having to > deal with reference counting problems involving objects made earlier. > I moved the thread creation after the short circuiting, but I cannot be moved up further because we have to figure out the type of event. > Sami> + /* Check if the signal is "Signal 0" or "Trace/breakpoint trap". */ > Sami> + if ((strcmp (stop_signal, "0") != 0) > Sami> +&& (strcmp (stop_signal, "SIGTRAP") != 0)) > > I didn't look this up, but this seems questionable. > Is this really how this is done? > I improved this by using enum target_signal and target_signal_to_name to convert the signal to a string when notifying python listeners. That looks OK IMO, but we can also create a module gdb.signal, create a pyhon Signal type, add Signal types for all signals to gdb.signal, and use a Signal object to notify python listeners. > Sami> +typedef struct > Sami> +{ > Sami> + PyObject *inferior_thread; > Sami> + event_object event; > Sami> +} stop_event_object; > > For the inheritance scheme to work, the 'event' field has to come first. > I didn't audit the other event object types, but please make sure they > are all correct. > Corrected and checked other objects.