use RAII in dispatcher to avoid refcount leaks in certain circumstances when handling exceptions

This commit is contained in:
Wenzel Jakob 2016-01-17 22:36:36 +01:00
parent 66c9a40213
commit f4671f6a04

View File

@ -227,20 +227,20 @@ private:
*result = (PyObject *) 1; *result = (PyObject *) 1;
try { try {
for (; it != nullptr; it = it->next) { for (; it != nullptr; it = it->next) {
PyObject *args_ = args; object args_(args, true);
int kwargs_consumed = 0; int kwargs_consumed = 0;
if (nargs < (int) it->args.size()) { if (nargs < (int) it->args.size()) {
args_ = PyTuple_New(it->args.size()); args_ = object(PyTuple_New(it->args.size()), false);
for (int i = 0; i < nargs; ++i) { for (int i = 0; i < nargs; ++i) {
PyObject *item = PyTuple_GET_ITEM(args, i); PyObject *item = PyTuple_GET_ITEM(args, i);
Py_INCREF(item); Py_INCREF(item);
PyTuple_SET_ITEM(args_, i, item); PyTuple_SET_ITEM(args_.ptr(), i, item);
} }
int arg_ctr = 0; int arg_ctr = 0;
for (auto const &it2 : it->args) { for (auto const &it2 : it->args) {
int index = arg_ctr++; int index = arg_ctr++;
if (PyTuple_GET_ITEM(args_, index)) if (PyTuple_GET_ITEM(args_.ptr(), index))
continue; continue;
PyObject *value = nullptr; PyObject *value = nullptr;
if (kwargs) if (kwargs)
@ -251,7 +251,7 @@ private:
value = it2.value; value = it2.value;
if (value) { if (value) {
Py_INCREF(value); Py_INCREF(value);
PyTuple_SET_ITEM(args_, index, value); PyTuple_SET_ITEM(args_.ptr(), index, value);
} else { } else {
kwargs_consumed = -1; /* definite failure */ kwargs_consumed = -1; /* definite failure */
break; break;
@ -260,11 +260,7 @@ private:
} }
if (kwargs_consumed == nkwargs) if (kwargs_consumed == nkwargs)
result = it->impl(it, args_, parent); result = it->impl(it, args_.ptr(), parent);
if (args_ != args) {
Py_DECREF(args_);
}
if (result != (PyObject *) 1) if (result != (PyObject *) 1)
break; break;
@ -868,15 +864,13 @@ private:
instance_type *inst = (instance_type *) inst_; instance_type *inst = (instance_type *) inst_;
try { try {
new (&inst->holder) holder_type( new (&inst->holder) holder_type(
inst->value->shared_from_this() inst->value->shared_from_this());
);
} catch (const std::bad_weak_ptr &) { } catch (const std::bad_weak_ptr &) {
new (&inst->holder) holder_type(inst->value); new (&inst->holder) holder_type(inst->value);
} }
inst->constructed = true; inst->constructed = true;
} }
static void dealloc(PyObject *inst_) { static void dealloc(PyObject *inst_) {
instance_type *inst = (instance_type *) inst_; instance_type *inst = (instance_type *) inst_;
if (inst->owned) { if (inst->owned) {