New issue 286 by pkwar...@gmail.com: Inconsistency with repeated fields
using C++ protobufs
http://code.google.com/p/protobuf/issues/detail?id=286
What steps will reproduce the problem?
1. Compile the test.proto file attached to this ticket (protoc
--python_out=. test.proto).
2. Run test1.py with PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python and then
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp.
3. Run test2.py with PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python and then
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp.
What is the expected output? What do you see instead?
test1.py:
$ PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp python ./test1.py
libprotobuf FATAL google/protobuf/reflection_ops.cc:51] CHECK failed:
(&from) != (to):
terminate called after throwing an instance
of 'google::protobuf::FatalException'
what(): CHECK failed: (&from) != (to):
Abort trap
$ PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python python ./test1.py
repeated {
name: "A"
value: "1"
}
test2.py:
$ PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp python ./test2.py
repeated {
}
$ PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python python ./test2.py
repeated {
name: "B"
value: "4"
}
What version of the product are you using? On what operating system?
protobuf 2.4.1
Please provide any additional information below.
Attachments:
test.proto 138 bytes
test1.py 245 bytes
test2.py 245 bytes
Thanks for reporting this.
I believe what's happening here is some problems with Python refcounting
and the fact that the C++ implementation reuses submessages to avoid
reallocations.
keepitems = [r for r in p.repeated if r.name != 'B']
- this line ends up copying python objects wrapping the pointers to C++
objects stored in the repeated field of messages
del p.repeated[:]
- this line causes the C++ code to clear the repeated field. Under the
hood, the C++ objects are not deleted, but Clear()'ed. The implementation
is unaware that there are still python objects wrapping the C++ objects.
p.repeated.extend(keepitems)
- causes RepeatedPtrField::Add() to be called, which now returns the same
instances as were previously used.
In test1.py, keepitems contains a python object wrapping what's supposed to
be the 'A' object. When extend() is called, the same underlying C++ object
is used, causing the crash, so when it tries to copy the data over using
MergeFrom(), the crash is triggered.
In test2.py, keepitems contains a python object wrapping what's supposed to
be the 'B' object, except that C++ message has been cleared. When extend()
is called, the C++ object originally used to store the 'A' object is
returned. The MergeFrom() call succeeds, but since the message has been
cleared, you get an empty object.
I'm not familiar enough with Python and C extensions to propose a fix, or
even to know how the pure Python implementation handles this. Jisi, any
ideas on that or even just an owner for this bug?
Comment #2 on issue 286 by jas...@google.com: Inconsistency with repeated
fields using C++ protobufs
http://code.google.com/p/protobuf/issues/detail?id=286
Oh, it turns out this is a known issue, and we have a bug tracking this
internally. Unfortunately, there isn't a lot of available bandwidth to work
out the issues in the python cpp implementation, so progress has been slow.
We'll post updates as they become available.