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 on clean-up with count example from docstrings #21824

Closed
jorisvandenbossche opened this issue Jul 8, 2018 · 16 comments · Fixed by #32842
Closed

Segfault on clean-up with count example from docstrings #21824

jorisvandenbossche opened this issue Jul 8, 2018 · 16 comments · Fixed by #32842
Labels
Bug Segfault Non-Recoverable Error
Milestone

Comments

@jorisvandenbossche
Copy link
Member

jorisvandenbossche commented Jul 8, 2018

In #19952 I have problems with a segfault when running doctests, and I could isolate at least the following code snippet that segfaults on clean-up (so only when exiting the process; an explicit del + gc.collect does not yet trigger the segfault).

import numpy as  np
import pandas as pd

df = pd.DataFrame({"Person": ["John", "Myla", None, "John", "Myla"],
                   "Age": [24., np.nan, 21., 33, 26],
                   "Single": [False, True, True, True, False]})
                  
res = df.set_index(["Person", "Single"]).count(level="Person")
@jorisvandenbossche
Copy link
Member Author

OK, and the cause is the missing value in the 'Person' level.

Simplified example:

In [1]: df = pd.DataFrame({"A": ["a", "b", None, "a", "b"],
   ...:                    "B": 1,
   ...:                    "C": range(5)})
   ...:                   
   ...: res = df.set_index(["A", "B"]).count(level="A")

In [2]: res
Out[2]: 
   B
A   
a  2
b  2

is causing the segfault (and without the None it does not).
But, when selecting the column, it does not produce a segfault, but it also gives a different result (the NaN is included in index):

In [1]: df = pd.DataFrame({"A": ["a", "b", None, "a", "b"],
   ...:                    "B": 1,
   ...:                    "C": range(5)})
   ...:                   
   ...: res = df.set_index(["A", "B"])['C'].count(level="A")

In [2]: res
Out[2]: 
A
a      2
b      2
NaN    1
Name: C, dtype: int64

Here the segfault does not happen, but it seems buggy behaviour, as count should not count the NaNs ?

@jorisvandenbossche jorisvandenbossche added this to the 0.24.0 milestone Jul 9, 2018
jorisvandenbossche added a commit to jorisvandenbossche/pandas that referenced this issue Aug 15, 2018
TomAugspurger added a commit to TomAugspurger/pandas that referenced this issue Aug 18, 2018
commit b29dfc6
Author: Tom Augspurger <tom.w.augspurger@gmail.com>
Date:   Thu Aug 16 10:45:38 2018 -0500

    Support NDFrame.shift with EAs

    Uses take internally.

    Closes pandas-dev#22386

commit b5d81cf
Author: William Ayd <william.ayd@icloud.com>
Date:   Thu Aug 16 03:54:18 2018 -0700

    Bump pytest (pandas-dev#22320)

commit f07a790
Author: jbrockmendel <jbrockmendel@gmail.com>
Date:   Thu Aug 16 03:46:58 2018 -0700

    Make more of numpy_helper unnecessary (pandas-dev#22344)

commit 7b80d4d
Author: Graham Inggs <graham.inggs+github@gmail.com>
Date:   Thu Aug 16 12:43:02 2018 +0200

    Drop redundant TestLocale (pandas-dev#22349)

commit 6bcfc46
Author: Matthew Roeschke <emailformattr@gmail.com>
Date:   Thu Aug 16 03:32:31 2018 -0700

    Fix failing dateutil test (pandas-dev#22354)

commit 86e8f23
Author: jbrockmendel <jbrockmendel@gmail.com>
Date:   Thu Aug 16 03:08:09 2018 -0700

    remove last cython: nprofile comments (pandas-dev#22371)

commit 70e6f7c
Author: Joris Van den Bossche <jorisvandenbossche@gmail.com>
Date:   Wed Aug 15 18:09:50 2018 +0200

    DOC: edit docstring example to prevent segfault (pandas-dev#21824) (pandas-dev#22368)
TomAugspurger added a commit to TomAugspurger/pandas that referenced this issue Aug 18, 2018
commit c4b0b97
Author: Tom Augspurger <tom.w.augspurger@gmail.com>
Date:   Thu Aug 16 14:36:39 2018 -0500

    Slice based

commit c980035
Author: Tom Augspurger <tom.w.augspurger@gmail.com>
Date:   Thu Aug 16 14:20:21 2018 -0500

    Updated

commit b29dfc6
Author: Tom Augspurger <tom.w.augspurger@gmail.com>
Date:   Thu Aug 16 10:45:38 2018 -0500

    Support NDFrame.shift with EAs

    Uses take internally.

    Closes pandas-dev#22386

commit b5d81cf
Author: William Ayd <william.ayd@icloud.com>
Date:   Thu Aug 16 03:54:18 2018 -0700

    Bump pytest (pandas-dev#22320)

commit f07a790
Author: jbrockmendel <jbrockmendel@gmail.com>
Date:   Thu Aug 16 03:46:58 2018 -0700

    Make more of numpy_helper unnecessary (pandas-dev#22344)

commit 7b80d4d
Author: Graham Inggs <graham.inggs+github@gmail.com>
Date:   Thu Aug 16 12:43:02 2018 +0200

    Drop redundant TestLocale (pandas-dev#22349)

commit 6bcfc46
Author: Matthew Roeschke <emailformattr@gmail.com>
Date:   Thu Aug 16 03:32:31 2018 -0700

    Fix failing dateutil test (pandas-dev#22354)

commit 86e8f23
Author: jbrockmendel <jbrockmendel@gmail.com>
Date:   Thu Aug 16 03:08:09 2018 -0700

    remove last cython: nprofile comments (pandas-dev#22371)

commit 70e6f7c
Author: Joris Van den Bossche <jorisvandenbossche@gmail.com>
Date:   Wed Aug 15 18:09:50 2018 +0200

    DOC: edit docstring example to prevent segfault (pandas-dev#21824) (pandas-dev#22368)
@jbrockmendel jbrockmendel added the Segfault Non-Recoverable Error label Nov 9, 2018
@jreback
Copy link
Contributor

jreback commented Dec 2, 2018

is this example fixed? is this just a tracking issue for finding the cause?

@pandas-dev/pandas-core

@gfyoung
Copy link
Member

gfyoung commented Dec 2, 2018

@jreback : Not really sure? The examples don't seem to segfault for me...

cc @jorisvandenbossche

Actually, I take that back. They do. Just as I exited the Python console.

@jreback jreback modified the milestones: 0.24.0, 0.24.1 Dec 9, 2018
@gfyoung
Copy link
Member

gfyoung commented Jan 27, 2019

@jorisvandenbossche : This issue has gone quiet for a little while, but I tried running your examples again, and it seems like the second example you gave, while the first and third ones are still buggy...

That's quite odd.

@gfyoung
Copy link
Member

gfyoung commented Jan 28, 2019

as count should not count the NaNs?

@jorisvandenbossche : I think that refers to values being counted. NaN can be considered one of the "groups" when using the level parameter.

@TomAugspurger
Copy link
Contributor

Pushing to 0.24.2.

@TomAugspurger TomAugspurger modified the milestones: 0.24.1, 0.24.2 Jan 30, 2019
@jorisvandenbossche jorisvandenbossche modified the milestones: 0.24.2, 0.25.0 Jan 30, 2019
@jorisvandenbossche
Copy link
Member Author

And directly pushed it to 0.25.0. It is not a critical bug (just a nasty one to find out)

@jorisvandenbossche
Copy link
Member Author

is this just a tracking issue for finding the cause?

Yes. From what I recall, somewhere in count an invalid dataframe gets created. Or at least, it doesn't look invalid (the repr is fine), but after that when closing the python session, it segfaults. Didn't get any further than that I think.

@jreback
Copy link
Contributor

jreback commented Jun 8, 2019

is this still an issue?

@jorisvandenbossche
Copy link
Member Author

Re-ran the example in the second post, and yes, this still segfaults on clean-up

@jorisvandenbossche jorisvandenbossche modified the milestones: 0.25.0, 1.0 Jun 30, 2019
@mroeschke
Copy link
Member

Both examples are working on master. Suppose this could use a regression test.

In [28]: In [1]: df = pd.DataFrame({"A": ["a", "b", None, "a", "b"],
    ...:    ...:                    "B": 1,
    ...:    ...:                    "C": range(5)})
    ...:    ...:
    ...:    ...: res = df.set_index(["A", "B"]).count(level="A")

In [29]: res
Out[29]:
   C
A
a  2
b  2

In [30]: In [1]: df = pd.DataFrame({"A": ["a", "b", None, "a", "b"],
    ...:    ...:                    "B": 1,
    ...:    ...:                    "C": range(5)})
    ...:    ...:
    ...:    ...: res = df.set_index(["A", "B"])['C'].count(level="A")

In [31]: res
Out[31]:
A
a      2
b      2
NaN    1
Name: C, dtype: int64

In [32]: pd.__version__
Out[32]: '0.26.0.dev0+555.gf7d162b18'

@mroeschke mroeschke removed the Bug label Oct 13, 2019
@mroeschke mroeschke added good first issue Needs Tests Unit test(s) needed to prevent regressions and removed Segfault Non-Recoverable Error labels Oct 13, 2019
@jorisvandenbossche
Copy link
Member Author

I still see the issue (it's only on clean-up, you have to close your session to see it)

@jorisvandenbossche jorisvandenbossche added Bug Segfault Non-Recoverable Error and removed Needs Tests Unit test(s) needed to prevent regressions good first issue labels Oct 13, 2019
@mroeschke
Copy link
Member

Ah! I see. Sorry didn't realize it was on cleanup.

@WillAyd
Copy link
Member

WillAyd commented Dec 17, 2019

I couldn't get a segfault on any of these on master during execution or while exiting - still an issue?

@jorisvandenbossche
Copy link
Member Author

On latest master, it now even directly segfaults for me (not only on exit):

In [1]: In [1]: df = pd.DataFrame({"A": ["a", "b", None, "a", "b"], 
   ...:    ...:                    "B": 1, 
   ...:    ...:                    "C": range(5)}) 
   ...:    ...:                    
   ...:    ...: res = df.set_index(["A", "B"]).count(level="A")                                                                                                                                                    

In [2]: corrupted size vs. prev_size                                                                                                                                                                               
Aborted (core dumped)

@TomAugspurger TomAugspurger modified the milestones: 1.0, Contributions Welcome Dec 30, 2019
@WillAyd
Copy link
Member

WillAyd commented Jan 16, 2020

I was able to generate a core dump for this and as far as I can tell the segfault happens in internals.pyx and has something to do with _as_array.

Here is the generated code for internals where I think this segfault starts:

frame #8: 0x000000011eaae0a2 internals.cpython-37m-darwin.so`__pyx_tp_dealloc_6pandas_5_libs_9internals_BlockPlacement(o=0x000000011f326ad0) at internals.c:25132:3 [opt]
   25129	  #endif
   25130	  PyObject_GC_UnTrack(o);
   25131	  Py_CLEAR(p->_as_slice);
-> 25132	  Py_CLEAR(p->_as_array);
   25133	  (*Py_TYPE(o)->tp_free)(o);
   25134	}

Everything else I see in the traceback would be either numpy or stdlib

    frame #0: 0x00007fff644a37fa libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff64560bc1 libsystem_pthread.dylib`pthread_kill + 432
    frame #2: 0x00007fff6442aa1c libsystem_c.dylib`abort + 120
    frame #3: 0x00007fff64520647 libsystem_malloc.dylib`malloc_vreport + 548
    frame #4: 0x00007fff6452340e libsystem_malloc.dylib`malloc_report + 151
    frame #5: 0x000000011095eea0 _multiarray_umath.cpython-37m-darwin.so`_buffer_clear_info + 144
    frame #6: 0x000000011095ede8 _multiarray_umath.cpython-37m-darwin.so`_dealloc_cached_buffer_info + 88
    frame #7: 0x0000000110918b62 _multiarray_umath.cpython-37m-darwin.so`array_dealloc + 18
    frame #8: 0x000000011eaae0a2 internals.cpython-37m-darwin.so`__pyx_tp_dealloc_6pandas_5_libs_9internals_BlockPlacement(o=0x000000011f326ad0) at internals.c:25132:3 [opt]
    frame #9: 0x000000010e278217 python`subtype_dealloc + 1207
    frame #10: 0x000000010e274c7b python`tupledealloc + 155
  * frame #11: 0x000000010e278217 python`subtype_dealloc + 1207
    frame #12: 0x000000010e24a8f1 python`dict_dealloc + 193
    frame #13: 0x000000010e2783a6 python`subtype_dealloc + 1606
    frame #14: 0x000000010e321cbf python`call_function + 815
    frame #15: 0x000000010e31d94f python`_PyEval_EvalFrameDefault + 32863
    frame #16: 0x000000010e3152c5 python`_PyEval_EvalCodeWithName + 3317
    frame #17: 0x000000010e310bcf python`builtin_exec + 767
    frame #18: 0x000000010e218226 python`_PyMethodDef_RawFastCallKeywords + 678
    frame #19: 0x000000010e21831a python`_PyCFunction_FastCallKeywords + 42
    frame #20: 0x000000010e321bf9 python`call_function + 617
    frame #21: 0x000000010e31d89f python`_PyEval_EvalFrameDefault + 32687
    frame #22: 0x000000010e22a748 python`gen_send_ex + 280
    frame #23: 0x000000010e31899f python`_PyEval_EvalFrameDefault + 12463
    frame #24: 0x000000010e22a748 python`gen_send_ex + 280
    frame #25: 0x000000010e31899f python`_PyEval_EvalFrameDefault + 12463
    frame #26: 0x000000010e22a748 python`gen_send_ex + 280
    frame #27: 0x000000010e218294 python`_PyMethodDef_RawFastCallKeywords + 788
    frame #28: 0x000000010e222828 python`_PyMethodDescr_FastCallKeywords + 88
    frame #29: 0x000000010e321c92 python`call_function + 770
    frame #30: 0x000000010e31d7e6 python`_PyEval_EvalFrameDefault + 32502
    frame #31: 0x000000010e2179f9 python`function_code_fastcall + 249
    frame #32: 0x000000010e321c6c python`call_function + 732
    frame #33: 0x000000010e31d89f python`_PyEval_EvalFrameDefault + 32687
    frame #34: 0x000000010e2179f9 python`function_code_fastcall + 249
    frame #35: 0x000000010e321c6c python`call_function + 732
    frame #36: 0x000000010e31d7e6 python`_PyEval_EvalFrameDefault + 32502
    frame #37: 0x000000010e3152c5 python`_PyEval_EvalCodeWithName + 3317
    frame #38: 0x000000010e217f63 python`_PyFunction_FastCallKeywords + 227
    frame #39: 0x000000010e321c6c python`call_function + 732
    frame #40: 0x000000010e31d94f python`_PyEval_EvalFrameDefault + 32863
    frame #41: 0x000000010e3152c5 python`_PyEval_EvalCodeWithName + 3317
    frame #42: 0x000000010e217f63 python`_PyFunction_FastCallKeywords + 227
    frame #43: 0x000000010e321c6c python`call_function + 732
    frame #44: 0x000000010e31d7e6 python`_PyEval_EvalFrameDefault + 32502
    frame #45: 0x000000010e3152c5 python`_PyEval_EvalCodeWithName + 3317
    frame #46: 0x000000010e217f63 python`_PyFunction_FastCallKeywords + 227
    frame #47: 0x000000010e321c6c python`call_function + 732
    frame #48: 0x000000010e31d7e6 python`_PyEval_EvalFrameDefault + 32502
    frame #49: 0x000000010e2179f9 python`function_code_fastcall + 249
    frame #50: 0x000000010e321c6c python`call_function + 732
    frame #51: 0x000000010e31d7e6 python`_PyEval_EvalFrameDefault + 32502
    frame #52: 0x000000010e3152c5 python`_PyEval_EvalCodeWithName + 3317
    frame #53: 0x000000010e217161 python`_PyFunction_FastCallDict + 945
    frame #54: 0x000000010e218ae0 python`_PyObject_Call_Prepend + 144
    frame #55: 0x000000010e218511 python`PyObject_Call + 241
    frame #56: 0x000000010e31db25 python`_PyEval_EvalFrameDefault + 33333
    frame #57: 0x000000010e3152c5 python`_PyEval_EvalCodeWithName + 3317
    frame #58: 0x000000010e217f63 python`_PyFunction_FastCallKeywords + 227
    frame #59: 0x000000010e321c6c python`call_function + 732
    frame #60: 0x000000010e31d89f python`_PyEval_EvalFrameDefault + 32687
    frame #61: 0x000000010e3152c5 python`_PyEval_EvalCodeWithName + 3317
    frame #62: 0x000000010e367854 python`PyRun_FileExFlags + 244
    frame #63: 0x000000010e366dda python`PyRun_SimpleFileExFlags + 474
    frame #64: 0x000000010e39248d python`pymain_main + 11421
    frame #65: 0x000000010e1f05ed python`main + 125
    frame #66: 0x00007fff6435c7fd libdyld.dylib`start + 1

@WillAyd WillAyd mentioned this issue Jan 17, 2020
1 task
@jreback jreback modified the milestones: Contributions Welcome, 1.1 Mar 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Segfault Non-Recoverable Error
Projects
None yet
7 participants