Skip to content

Commit bd80101

Browse files
committed
Fix property setters not sending correct D-Bus errors
1 parent 20b25d3 commit bd80101

File tree

2 files changed

+74
-6
lines changed

2 files changed

+74
-6
lines changed

src/sdbus/sd_bus_internals_interface.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
License along with this library; if not, write to the Free Software
1919
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2020
*/
21-
#include <systemd/sd-bus.h>
2221
#include "sd_bus_internals.h"
2322

2423
// TODO: adding interface to different buses, recalculating vtable
@@ -458,14 +457,21 @@ static int _SdBusInterface_property_set_callback(sd_bus* Py_UNUSED(bus),
458457
const char* property,
459458
sd_bus_message* value,
460459
void* userdata,
461-
sd_bus_error* Py_UNUSED(ret_error)) {
460+
sd_bus_error* ret_error) {
462461
SdBusInterfaceObject* self = userdata;
463-
PyObject* property_name_bytes CLEANUP_PY_OBJECT = PyBytes_FromString(property);
464-
PyObject* set_call = CALL_PYTHON_CHECK_RETURN_NEG1(PyDict_GetItem(self->property_set_dict, property_name_bytes));
462+
PyObject* property_name_bytes CLEANUP_PY_OBJECT = NULL;
463+
PyObject* new_message CLEANUP_PY_OBJECT = NULL;
464+
property_name_bytes = PyBytes_FromString(property);
465+
if (NULL == property_name_bytes) {
466+
goto fail;
467+
}
468+
PyObject* set_call = CALL_PYTHON_GOTO_FAIL(PyDict_GetItem(self->property_set_dict, property_name_bytes));
465469

466-
PyObject* new_message CLEANUP_PY_OBJECT = CALL_PYTHON_CHECK_RETURN_NEG1(SD_BUS_PY_CLASS_DUNDER_NEW(SdBusMessage_class));
470+
new_message = CALL_PYTHON_GOTO_FAIL(SD_BUS_PY_CLASS_DUNDER_NEW(SdBusMessage_class));
467471
_SdBusMessage_set_messsage((SdBusMessageObject*)new_message, value);
468472

469-
Py_XDECREF(CALL_PYTHON_CHECK_RETURN_NEG1(PyObject_CallFunctionObjArgs(set_call, new_message, NULL)));
473+
Py_XDECREF(CALL_PYTHON_GOTO_FAIL(PyObject_CallFunctionObjArgs(set_call, new_message, NULL)));
470474
return 0;
475+
fail:
476+
return set_dbus_error_from_python_exception(ret_error);
471477
}

test/test_low_level_errors.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ class IndependentError(Exception):
4343
...
4444

4545

46+
GOOD_STR = 'Good'
47+
48+
4649
class InterfaceWithErrors(
4750
DbusInterfaceCommonAsync,
4851
interface_name='org.example.test',
@@ -63,6 +66,22 @@ async def hello_error(self) -> str:
6366
async def hello_world(self) -> str:
6467
return HELLO_WORLD
6568

69+
@dbus_property_async('s')
70+
def indep_err_setable(self) -> str:
71+
return GOOD_STR
72+
73+
@indep_err_setable.setter
74+
def indep_err_setter(self, new_value: str) -> None:
75+
raise IndependentError
76+
77+
@dbus_property_async('s')
78+
def derrive_err_settable(self) -> str:
79+
return GOOD_STR
80+
81+
@derrive_err_settable.setter
82+
def derrive_err_setter(self, new_value: str) -> None:
83+
raise DbusDerivePropertydError
84+
6685

6786
class TestLowLevelErrors(IsolatedDbusTestCase):
6887
async def asyncSetUp(self) -> None:
@@ -100,3 +119,46 @@ async def test_property_getter_derived_error(self) -> None:
100119
self.test_object_connection.derrive_err_getter.get_async(),
101120
timeout=1,
102121
)
122+
123+
await self.test_object_connection.hello_world()
124+
125+
async def test_property_setter_independent_error(self) -> None:
126+
127+
self.assertEqual(
128+
await wait_for(
129+
self.test_object_connection.indep_err_setable.get_async(),
130+
timeout=1,
131+
),
132+
GOOD_STR,
133+
)
134+
135+
with self.assertRaises(DbusFailedError) as cm:
136+
await wait_for(
137+
self.test_object_connection.
138+
indep_err_setable.set_async('Test'),
139+
timeout=1,
140+
)
141+
142+
should_be_dbus_failed = cm.exception
143+
self.assertIs(should_be_dbus_failed.__class__, DbusFailedError)
144+
145+
await self.test_object_connection.hello_world()
146+
147+
async def test_property_setter_derived_error(self) -> None:
148+
149+
self.assertEqual(
150+
await wait_for(
151+
self.test_object_connection.derrive_err_settable.get_async(),
152+
timeout=1,
153+
),
154+
GOOD_STR,
155+
)
156+
157+
with self.assertRaises(DbusDerivePropertydError):
158+
await wait_for(
159+
self.test_object_connection.
160+
derrive_err_settable.set_async('Test'),
161+
timeout=1,
162+
)
163+
164+
await self.test_object_connection.hello_world()

0 commit comments

Comments
 (0)