Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault after obspy.read #1658

Merged
merged 9 commits into from Mar 24, 2017
Merged

Segfault after obspy.read #1658

merged 9 commits into from Mar 24, 2017

Conversation

krischer
Copy link
Member

Hi devs, running the QC we are sometimes running in to a segfault reading the record headers of some files. It's been quite a challenge but I traced it back to the obspy.read subroutine... it really blows my mind.

from obspy import read
from obspy.io.mseed.util import get_flags

# Reading the file before getting the records causes a segfault
# when getting header flags.
read("broken_records.mseed")
get_flags("broken_records.mseed")

>>> Warning: Number of blockettes in fixed header (2) does not match the number parsed (1)
>>> Segmentation fault (core dumped)

When we do not read the file first the segmentation fault does not occur.:

from obspy import read
from obspy.io.mseed.util import get_flags

get_flags("broken_records.mseed")

>>> Warning: Number of blockettes in fixed header (2) does not match the number parsed (1)
>>> Warning: Number of blockettes in fixed header (2) does not match the number parsed (1)
>>> ... identical for all 16 records

Here is the file: ftp://www.orfeus-eu.org/pub/outgoing/broken_records.mseed (8 kb).

Thanks for the help and hope you understand this behaviour better than me..

@Jollyfant Jollyfant added .io.mseed bug confirmed bug labels Feb 1, 2017
@megies
Copy link
Member

megies commented Feb 8, 2017

I can confirm the problem.. no idea what's going on though..

@megies megies added this to the 1.1.0 milestone Feb 8, 2017
@megies megies added the release blocker critical issues blocking the corresponding future release label Feb 27, 2017
@megies
Copy link
Member

megies commented Mar 22, 2017

Any new insights for this one @Jollyfant?

@Jollyfant
Copy link
Contributor Author

Nope.. I'm putting my money on @krischer for this one.

@megies
Copy link
Member

megies commented Mar 22, 2017

Might be connected to #1728..?

@krischer
Copy link
Member

This is now A PR fixing the issue.

The problem was that the call to read_mseed() hooked up libmseed's logging to some Python callbacks. Leaving the read function the Python functions were garbage collected and a call the next time naturally resulted in a segfault.

There is now a wrapper around the ctypes lib to always setup the logging so this can no longer happen and it is completely transparent to anyone directly using libmseed from Python.

Does not fix #1728 which is another issue.

@krischer
Copy link
Member

IMHO ready to go.

Now called InternalMSEEDError instead of InternalMSEEDReadingError and
InternalMSEEDWarning instead of InternalMSEEDReadingWarnings as both can
now also be raised in non-reading contexts.
Copy link
Contributor

@Jollyfant Jollyfant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrapper appears to be good and is covered by tests.

@krischer krischer merged commit c147e47 into master Mar 24, 2017
Copy link
Member

@QuLogic QuLogic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There were still a few issues...

CHANGELOG.txt Outdated
@@ -92,6 +92,9 @@ master: (doi: 10.5281/zenodo.165135)
some rare segfaults. (see #1658)
* Update to libmseed v2.19.2 (see #1703).
* Correctly read MiniSEED files with a data offset of 48 bytes (see #1540).
* InternalMSEEDReadingError now called InternalMSEEDError and
InternalMSEEDReadingWarning now called of InternalMSEEDWarning as both
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra of

@@ -581,11 +497,11 @@ class MSTraceSeg(C.Structure):
('samprate', C.c_double), # Nominal sample rate (Hz)
('samplecnt', C.c_int64), # Number of samples in trace coverage
('datasamples', C.c_void_p), # Data samples, 'numsamples' of type
# 'sampletype'
# 'sampletype'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrapped from the previous line; looks pretty weird unindented like this.


def _wrapper(*args):
# Collect exceptions. They cannot be raised in the callback as
# they could never be caught then. They are collected an raised
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/an/and/

_warns.append(msg)

diag_print = \
C.CFUNCTYPE(C.c_void_p, C.c_char_p)(log_error_or_warning)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return type is None, not c_void_p.

def log_message(msg):
if self.verbose:
print(msg[6:].strip())
log_print = C.CFUNCTYPE(C.c_void_p, C.c_char_p)(log_message)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return type is None, not c_void_p.

# this is completely different to C.c_char_p which is a string
__clibmseed.mst_packgroup.argtypes = [
C.POINTER(MSTraceGroup), C.CFUNCTYPE(
C.c_void_p, C.POINTER(C.c_char), C.c_int, C.c_void_p),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None, not c_void_p (the first time).

__clibmseed.mst_packgroup.argtypes = [
C.POINTER(MSTraceGroup), C.CFUNCTYPE(
C.c_void_p, C.POINTER(C.c_char), C.c_int, C.c_void_p),
C.c_void_p, C.c_int, C.c_short, C.c_short, C.POINTER(C.c_int), C.c_short,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C.POINTER(C.c_int64), actually

C.c_int8,
C.CFUNCTYPE(C.c_void_p, C.c_char_p),
C.CFUNCTYPE(C.c_void_p, C.c_char_p)]
__clibmseed.setupLogging.restype = C.c_void_p
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None


__clibmseed.msr_free.argtypes = [C.POINTER(C.POINTER(MSRecord))]
__clibmseed.msr_free.restype = C.c_void_p
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None


__clibmseed.lil_free.argtypes = [C.POINTER(LinkedIDList)]
__clibmseed.lil_free.restype = C.c_void_p
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None

@megies
Copy link
Member

megies commented Mar 25, 2017

Thanks for the review @QuLogic, I've opened a follow up issue to make sure your comments don't go unnoticed..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug confirmed bug .io.mseed release blocker critical issues blocking the corresponding future release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants