qom: avoid reporting errors for NULL error object
PATCH 1/1 qom: avoid reporting errors for NULL error object
When debugging QEMU it is often useful to put a breakpoint on the error_setg_internal method impl.
Unfortunately the object_property_add / object_class_property_add methods call object_property_find / object_class_property_find methods to check if a property exists already before adding the new property.
As a result there are a huge number of calls to error_setg_internal on startup of most QEMU commands, making it very painful to set a breakpoint on this method.
This puts a minor optimization on the code so that we avoid calling error_setg() when errp is NULL. Functionally there's no difference since error_setg() is a no-op when errp is NULL, but this lets us use breakpoints in GDB in a practical way.
--- qom/object.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
qom/object.c +10 -2
@@ -1087,7 +1087,12 @@ ObjectProperty *object_property_find(Object *obj, const char *name,return prop; } -error_setg (errp,"Property '.%s' not found" , name); +/* Optimized to avoid calling error_setg if errp == NULL +* otherwise every property add call hits error_setg +* making it impratical to set breakpoints in GDB */ +if (errp) { +error_setg (errp,"Property '.%s' not found" , name); + }return NULL ; }
@@ -1133,7 +1138,10 @@ ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, } prop =g_hash_table_lookup (klass->properties, name); -if (!prop) { +/* Optimized to avoid calling error_setg if errp == NULL +* otherwise every property add call hits error_setg +* making it impratical to set breakpoints in GDB */ +if (!prop && errp) {error_setg (errp,"Property '.%s' not found" , name); }return prop;
Signature · 1 line
2.19.1
Hi
Quoted 12 lines · Daniel P. Berrangé
When debugging QEMU it is often useful to put a breakpoint on the
error_setg_internalmethod impl.Unfortunately the
object_property_add/object_class_property_addmethods callobject_property_find/object_class_property_findmethods to check if a property exists already before adding the new property.As a result there are a huge number of calls to
error_setg_internalon startup of most QEMU commands, making it very painful to set a breakpoint on this method.
Quoted 6 lines
This puts a minor optimization on the code so that we avoid calling
error_setg()when errp is NULL. Functionally there's no difference sinceerror_setg()is a no-op when errp is NULL, but this lets us use breakpoints in GDB in a practical way.Signed-off-by Daniel P. Berrangé <[email protected]>
Or maybe change the error_setg* macros? After all, if errp is NULL, it's an error qemu can handle.
Quoted 38 lines
--- qom/object.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)qom/object.c +10
-3@@ -1087,7 +1087,12 @@ ObjectProperty *object_property_find(Object *obj, const char *name,return prop; } -error_setg (errp,"Property '.%s' not found" , name); +/* Optimized to avoid calling error_setg if errp == NULL +* otherwise every property add call hits error_setg +* making it impratical to set breakpoints in GDB */ +if (errp) { +error_setg (errp,"Property '.%s' not found" , name); + }return NULL ; }@@ -1133,7 +1138,10 @@ ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, } prop =g_hash_table_lookup (klass->properties, name); -if (!prop) { +/* Optimized to avoid calling error_setg if errp == NULL +* otherwise every property add call hits error_setg +* making it impratical to set breakpoints in GDB */ +if (!prop && errp) {error_setg (errp,"Property '.%s' not found" , name); }return prop; --2.19.1
Signature · 1 line
Marc-André Lureau
Quoted 20 lines · Marc-André Lureau
Hi
Quoted 17 lines · Daniel P. Berrangé
When debugging QEMU it is often useful to put a breakpoint on the
error_setg_internalmethod impl.Unfortunately the
object_property_add/object_class_property_addmethods callobject_property_find/object_class_property_findmethods to check if a property exists already before adding the new property.As a result there are a huge number of calls to
error_setg_internalon startup of most QEMU commands, making it very painful to set a breakpoint on this method.This puts a minor optimization on the code so that we avoid calling
error_setg()when errp is NULL. Functionally there's no difference sinceerror_setg()is a no-op when errp is NULL, but this lets us use breakpoints in GDB in a practical way.
Quoted 4 lines
Quoted 1 line
Signed-off-by Daniel P. Berrangé <[email protected]>Or maybe change the error_setg* macros? After all, if errp is NULL, it's an error qemu can handle.
That would mean that all callers would get short circuited which I don't think it is desirable in general.
This QOM usage is special in that the calling code is using the error scenario as a means to trigger different code flow. IOW it doesn't consider it an error scenario at all.
Quoted 25 lines
Quoted 25 lines
--- qom/object.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)qom/object.c +6
-1@@ -1087,7 +1087,12 @@ ObjectProperty *object_property_find(Object *obj, const char *name,return prop; } -error_setg (errp,"Property '.%s' not found" , name); +/* Optimized to avoid calling error_setg if errp == NULL +* otherwise every property add call hits error_setg +* making it impratical to set breakpoints in GDB */ +if (errp) { +error_setg (errp,"Property '.%s' not found" , name); + }return NULL ; }@@ -1133,7 +1138,10 @@ ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, }
Quoted 17 lines
Quoted 13 lines
qom/object.c +4
-2prop =g_hash_table_lookup (klass->properties, name); -if (!prop) { +/* Optimized to avoid calling error_setg if errp == NULL +* otherwise every property add call hits error_setg +* making it impratical to set breakpoints in GDB */ +if (!prop && errp) {error_setg (errp,"Property '.%s' not found" , name); }return prop; --2.19.1
Signature · 1 line
Marc-André Lureau
Regards,
Daniel
Signature · 3 lines
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
Quoted 29 lines · Daniel P. Berrangé
When debugging QEMU it is often useful to put a breakpoint on the
error_setg_internalmethod impl.Unfortunately the
object_property_add/object_class_property_addmethods callobject_property_find/object_class_property_findmethods to check if a property exists already before adding the new property.As a result there are a huge number of calls to
error_setg_internalon startup of most QEMU commands, making it very painful to set a breakpoint on this method.This puts a minor optimization on the code so that we avoid calling
error_setg()when errp is NULL. Functionally there's no difference sinceerror_setg()is a no-op when errp is NULL, but this lets us use breakpoints in GDB in a practical way.Signed-off-by Daniel P. Berrangé <[email protected]>--- qom/object.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)qom/object.c +0
-0@@ -1087,7 +1087,12 @@ ObjectProperty *object_property_find(Object *obj, const char *name,return prop; }
qom/object.c ObjectProperty *object_property_find(Object *obj, const char *name, · line 1098
Quoted 10 lines
qom/object.c +6
-1-error_setg (errp,"Property '.%s' not found" , name); +/* Optimized to avoid calling error_setg if errp == NULL +* otherwise every property add call hits error_setg +* making it impratical to set breakpoints in GDB */ +if (errp) { +error_setg (errp,"Property '.%s' not found" , name); + }return NULL ; }
In my opinion, this function's design is awkward. Stress on *opinion*.
On success, it returns a (non-null) pointer.
On failure, it sets an error and returns null. Note that it has just one failure mode: "Property '.%s' not found". Setting an error is just a convenience for those callers that want to propagate exactly this error to their callers.
I count 30 callers. Only six pass a non-NULL argument to @errp.
I'd rather have a pair of functions similar to how Python has both .get() and .__getitem__(): the former doesn't fail, but returns None instead, and the latter does fail, throwing KeyError. In QEMU, we can't throw, so we set an error. Here's the obvious code:
ObjectProperty *object_property_find(Object *obj, const char *name)
{
ObjectProperty *prop;
ObjectClass *klass = object_get_class(obj);
prop = object_class_property_find(klass, name, NULL);
if (prop) {
return prop;
}
prop = g_hash_table_lookup(obj->properties, name);
if (prop) {
return prop;
}
return NULL;
}
ObjectProperty *object_property_find_err(Object *obj, const char *name,
Error **errp)
{
ObjectProperty *prop = object_property_find(obj, name);
if (!prop) {
error_setg(errp, "Property '.%s' not found", name);
}
return prop;
}qom/object.c ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, · line 1147
Quoted 12 lines
qom/object.c +4
-1@@ -1133,7 +1138,10 @@ ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, } prop =g_hash_table_lookup (klass->properties, name); -if (!prop) { +/* Optimized to avoid calling error_setg if errp == NULL +* otherwise every property add call hits error_setg +* making it impratical to set breakpoints in GDB */ +if (!prop && errp) {error_setg (errp,"Property '.%s' not found" , name); }return prop;
Likewise, just more so: callers passing non-NULL do not exist.
Quoted 78 lines · Markus Armbruster
Quoted 29 lines · Daniel P. Berrangé
When debugging QEMU it is often useful to put a breakpoint on the
error_setg_internalmethod impl.Unfortunately the
object_property_add/object_class_property_addmethods callobject_property_find/object_class_property_findmethods to check if a property exists already before adding the new property.As a result there are a huge number of calls to
error_setg_internalon startup of most QEMU commands, making it very painful to set a breakpoint on this method.This puts a minor optimization on the code so that we avoid calling
error_setg()when errp is NULL. Functionally there's no difference sinceerror_setg()is a no-op when errp is NULL, but this lets us use breakpoints in GDB in a practical way.Signed-off-by Daniel P. Berrangé <[email protected]>--- qom/object.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)qom/object.c +0
-0@@ -1087,7 +1087,12 @@ ObjectProperty *object_property_find(Object *obj, const char *name,return prop; }qom/object.c ObjectProperty *object_property_find(Object *obj, const char *name, · line 1098
Quoted 10 lines
qom/object.c +6
-1-error_setg (errp,"Property '.%s' not found" , name); +/* Optimized to avoid calling error_setg if errp == NULL +* otherwise every property add call hits error_setg +* making it impratical to set breakpoints in GDB */ +if (errp) { +error_setg (errp,"Property '.%s' not found" , name); + }return NULL ; }In my opinion, this function's design is awkward. Stress on *opinion*.
On success, it returns a (non-null) pointer.
On failure, it sets an error and returns null. Note that it has just one failure mode: "Property '.%s' not found". Setting an error is just a convenience for those callers that want to propagate exactly this error to their callers.
I count 30 callers. Only six pass a non-NULL argument to @errp.
I'd rather have a pair of functions similar to how Python has both .get() and .__getitem__(): the former doesn't fail, but returns None instead, and the latter does fail, throwing KeyError. In QEMU, we can't throw, so we set an error. Here's the obvious code:
ObjectProperty *object_property_find(Object *obj, const char *name) { ObjectProperty *prop; ObjectClass *klass = object_get_class(obj); prop = object_class_property_find(klass, name, NULL); if (prop) { return prop; } prop = g_hash_table_lookup(obj->properties, name); if (prop) { return prop; } return NULL; } ObjectProperty *object_property_find_err(Object *obj, const char *name, Error **errp)
Quoted 8 lines
{
ObjectProperty *prop = object_property_find(obj, name);
if (!prop) {
error_setg(errp, "Property '.%s' not found", name);
}
return prop;
}Yes, I'd be happy with this approach as I think it is more useful in general
Regards,
Daniel
Signature · 3 lines
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|