With the advent of the Present extension, some events (such as
PresentCompleteNotify) now use native 64-bit types on the wire.
For XGE events, we insert an extra "uint32_t full_sequence" field
immediately after the first 32 bytes of data. Normally, this causes
the subsequent fields to be shifted over by 4 bytes, and the structure
to grow in size by 4 bytes. Everything works fine.
However, if event contains 64-bit extended fields, this may result in
the compiler adding an extra 4 bytes of padding so that those fields
remain aligned on 64-bit boundaries. This causes the structure to grow
by 8 bytes, not 4. Unfortunately, XCB doesn't realize this, and
always believes that the length only increased by 4. read_packet()
then fails to malloc enough memory to hold the event, and the event
processing code uses the wrong offsets.
To fix this, mark any event structures containing 64-bit extended
fields with __attribute__((__packed__)).
v2: Use any(...) instead of True in (...), as suggested by
Daniel Martin.
v3 (Alan Coopersmith): Fix build with Solaris Studio 12.3 by moving the
attribute to after the structure definition.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Keith Packard <keithp@keithp.com> [v1]
Reviewed-by: Josh Triplett <josh@joshtriplett.org> [v1]
Reviewed-by: Daniel Martin <consume.noise@gmail.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
# Iterator
_c_iterator(self, name)
# Iterator
_c_iterator(self, name)
+def _c_complex(self, force_packed = False):
'''
Helper function for handling all structure types.
Called for all structs, requests, replies, events, errors.
'''
Helper function for handling all structure types.
Called for all structs, requests, replies, events, errors.
if b.type.has_name:
_h(' } %s;', b.c_field_name)
if b.type.has_name:
_h(' } %s;', b.c_field_name)
- _h('} %s;', self.c_type)
+ _h('} %s%s;', 'XCB_PACKED ' if force_packed else '', self.c_type)
def c_struct(self, name):
'''
def c_struct(self, name):
'''
# events while generating the structure for them. Otherwise we would read
# garbage (the internal full_sequence) when accessing normal event fields
# there.
# events while generating the structure for them. Otherwise we would read
# garbage (the internal full_sequence) when accessing normal event fields
# there.
if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
event_size = 0
for field in self.fields:
if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
event_size = 0
for field in self.fields:
full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
idx = self.fields.index(field)
self.fields.insert(idx + 1, full_sequence)
full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
idx = self.fields.index(field)
self.fields.insert(idx + 1, full_sequence)
+
+ # If the event contains any 64-bit extended fields, they need
+ # to remain aligned on a 64-bit boundary. Adding full_sequence
+ # would normally break that; force the struct to be packed.
+ force_packed = any(f.type.size == 8 and f.type.is_simple for f in self.fields[(idx+1):])
break
_c_type_setup(self, name, ('event',))
break
_c_type_setup(self, name, ('event',))
if self.name == name:
# Structure definition
if self.name == name:
# Structure definition
+ _c_complex(self, force_packed)
+#define XCB_PACKED __attribute__((__packed__))
+
/**
* @defgroup XCB_Core_API XCB Core API
* @brief Core API of the XCB library.
/**
* @defgroup XCB_Core_API XCB Core API
* @brief Core API of the XCB library.