mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-24 06:05:10 +00:00
Fix premature destruction of args/kwargs arguments
The `py::args` or `py::kwargs` arguments aren't properly referenced when added to the function_call arguments list: their reference counts drop to zero if the first (non-converting) function call fails, which means they might be cleaned up before the second pass call runs. This commit adds a couple of extra `object`s to the `function_call` where we can stash a reference to them when needed to tie their lifetime to the function_call object's lifetime. (Credit to YannickJadoul for catching and proposing a fix in #1223).
This commit is contained in:
parent
53e0aa034b
commit
c715c70e0a
@ -1802,6 +1802,10 @@ struct function_call {
|
||||
/// The `convert` value the arguments should be loaded with
|
||||
std::vector<bool> args_convert;
|
||||
|
||||
/// Extra references for the optional `py::args` and/or `py::kwargs` arguments (which, if
|
||||
/// present, are also in `args` but without a reference).
|
||||
object args_ref, kwargs_ref;
|
||||
|
||||
/// The parent, if any
|
||||
handle parent;
|
||||
|
||||
|
@ -576,8 +576,8 @@ protected:
|
||||
continue; // Unconsumed kwargs, but no py::kwargs argument to accept them
|
||||
|
||||
// 4a. If we have a py::args argument, create a new tuple with leftovers
|
||||
tuple extra_args;
|
||||
if (func.has_args) {
|
||||
tuple extra_args;
|
||||
if (args_to_copy == 0) {
|
||||
// We didn't copy out any position arguments from the args_in tuple, so we
|
||||
// can reuse it directly without copying:
|
||||
@ -594,6 +594,7 @@ protected:
|
||||
}
|
||||
call.args.push_back(extra_args);
|
||||
call.args_convert.push_back(false);
|
||||
call.args_ref = std::move(extra_args);
|
||||
}
|
||||
|
||||
// 4b. If we have a py::kwargs, pass on any remaining kwargs
|
||||
@ -602,6 +603,7 @@ protected:
|
||||
kwargs = dict(); // If we didn't get one, send an empty one
|
||||
call.args.push_back(kwargs);
|
||||
call.args_convert.push_back(false);
|
||||
call.kwargs_ref = std::move(kwargs);
|
||||
}
|
||||
|
||||
// 5. Put everything in a vector. Not technically step 5, we've been building it
|
||||
|
Loading…
Reference in New Issue
Block a user