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

Figure.meca causes segmentation fault when given "event_name" via a DataFrame #2524

Closed
wasjabloch opened this issue Apr 27, 2023 · 11 comments · Fixed by #2582
Closed

Figure.meca causes segmentation fault when given "event_name" via a DataFrame #2524

wasjabloch opened this issue Apr 27, 2023 · 11 comments · Fixed by #2582
Labels
bug Something isn't working upstream Bug or missing feature of upstream core GMT
Milestone

Comments

@wasjabloch
Copy link

wasjabloch commented Apr 27, 2023

Description of the problem

When calling fig.meca(data, scale=".3") where data is a pandas DataFrame with a column called "event_name", a segmentation fault occurs.

Minimal Complete Verifiable Example

import pandas as pd
import pygmt
R = [-125, -122.25, 46, 48.5]
J = "M5c"
dat = pd.DataFrame(
    {"longitude": [-122.597],
     "latitude": [47.014],
     "depth": [50.0],
     "strike": [14.0],
     "dip": [82.0],
     "rake": [-135.0],
     "magnitude":  [6.7],
     "year": [1949],
     "size": [0.67],
     "event_name": ["1949 M6.7"]
     }
)
fig = pygmt.Figure()
fig.meca(dat, scale=".3", region=R, projection=J)

Full error message

free(): double free detected in tcache 2
Aborted (core dumped)

System information

PyGMT information:
  version: v0.9.0
System information:
  python: 3.10.10 | packaged by conda-forge | (main, Mar 24 2023, 20:08:06) [GCC 11.3.0]
  executable: /home/xxx/.conda/envs/gmt/bin/python
  machine: Linux-5.4.0-121-generic-x86_64-with-glibc2.31
Dependency information:
  numpy: 1.24.3
  pandas: 2.0.1
  xarray: 2023.4.2
  netCDF4: 1.6.3
  packaging: 23.1
  contextily: None
  geopandas: None
  ghostscript: 9.54.0
GMT library information:
  binary version: 6.4.0
  cores: 32
  grid layout: rows
  image layout: 
  library path: /home/xxx/.conda/envs/gmt/lib/libgmt.so
  padding: 2
  plugin dir: /home/xxx/.conda/envs/gmt/lib/gmt/plugins
  share dir: /home/xxx/.conda/envs/gmt/share/gmt
  version: 6.4.0
@wasjabloch wasjabloch added the bug Something isn't working label Apr 27, 2023
@welcome
Copy link

welcome bot commented Apr 27, 2023

👋 Thanks for opening your first issue here! Please make sure you filled out the template with as much detail as possible. You might also want to take a look at our contributing guidelines and code of conduct.

@wasjabloch
Copy link
Author

P.S.: I just saw that pygmt v0.9.0 is out. I'll now try to confirm the bug with the most recent version.

@wasjabloch
Copy link
Author

Confirmed with the most recent version. The bug report is now up to date.

@seisman
Copy link
Member

seisman commented Apr 28, 2023

Thanks. I can reproduce the issue. Will see why it happens later.

@seisman
Copy link
Member

seisman commented Jun 18, 2023

@PaulWessel This looks like an upstream bug to me, could you please see if you can verify and it?

Here is a minimal example to reproduce the issue:

import pandas as pd
import pygmt

pygmt.show_versions()
dat = pd.DataFrame(
    {
        "longitude": [-122.597],
        "latitude": [47.014],
        "depth": [50.0],
        "strike": [14.0],
        "dip": [82.0],
        "rake": [-135.0],
        "magnitude": [6.7],
        "event_name": ["Eventname"],
    }
)
fig = pygmt.Figure()
fig.meca(dat, scale="0.3", region=[-125, -122.25, 46, 48.5], projection="M5c")
fig.show()

Here are the verbose messages:

PyGMT information:
  version: v0.9.1.dev1+gaaa0ca006.d20230405
System information:
  python: 3.11.2 | packaged by conda-forge | (main, Mar 31 2023, 17:54:27) [Clang 14.0.6 ]
  executable: /Users/seisman/opt/miniconda/bin/python
  machine: macOS-13.3.1-x86_64-i386-64bit
Dependency information:
  numpy: 1.24.2
  pandas: 2.0.0
  xarray: 2022.12.0
  netCDF4: 1.6.3
  packaging: 23.0
  contextily: 1.2.0
  geopandas: 0.12.2
  IPython: 8.7.0
  rioxarray: 0.13.3
  ghostscript: 9.54.0
GMT library information:
  binary version: 6.5.0_f6d1b51_2023.06.16
  cores: 8
  grid layout: rows
  image layout:
  library path: /Users/seisman/opt/GMT-debug/lib/libgmt.dylib
  padding: 2
  plugin dir: /Users/seisman/opt/GMT-debug/lib/gmt/plugins
  share dir: /Users/seisman/opt/GMT-debug/share
  version: 6.5.0
gmtset [DEBUG]: gmtlib_get_graphics_item: Fig: 0 Subplot: 2 Panel: () Inset: 0
pygmt-session [DEBUG]: Exit:  gmt_reload_settings
pygmt-session [DEBUG]: Enter: gmtlib_plot_C_format
pygmt-session [DEBUG]: Exit:  gmtlib_plot_C_format
pygmt-session [DEBUG]: Enter: gmtinit_get_history
pygmt-session [DEBUG]: gmtlib_get_graphics_item: Fig: 0 Subplot: 2 Panel: () Inset: 0
pygmt-session [DEBUG]: Initialize FFTW with 8 threads.
pygmt-session [DEBUG]: GMT_Create_Session initialized GMT structure
pygmt-session [DEBUG]: Shared Library # 0 (core). Path = /Users/seisman/opt/GMT-debug/lib/libgmt.dylib
pygmt-session [DEBUG]: Loading GMT plugins from: /Users/seisman/opt/GMT-debug/lib/gmt/plugins
pygmt-session [DEBUG]: Shared Library # 1 (supplements). Path = /Users/seisman/opt/GMT-debug/lib/gmt/plugins/supplements.so
pygmt-session [DEBUG]: GMT now running in modern mode [Session ID = 61391]
pygmt-session [DEBUG]: GMT_Call_Command string: gmt figure d140f05165714c95a3a42cd454074ce1 -
pygmt-session [DEBUG]: Revised options: d140f05165714c95a3a42cd454074ce1 -
figure [DEBUG]: No figure file /Users/seisman/.gmt/sessions/gmt_session.61391/gmt.figures - nothing to do
figure (gmt_init.c:19445(gmt_add_figure)): FYI: gmt_M_free given a NULL pointer - ignored
figure [DEBUG]: New figure: 1	d140f05165714c95a3a42cd454074ce1	-
pygmt-session [DEBUG]: Exit:  gmt_reload_settings
pygmt-session [DEBUG]: Enter: gmtlib_plot_C_format
pygmt-session [DEBUG]: Exit:  gmtlib_plot_C_format
pygmt-session [DEBUG]: Enter: gmtinit_get_history
pygmt-session [DEBUG]: gmtlib_get_graphics_item: Fig: 1 Subplot: 2 Panel: () Inset: 0
pygmt-session [DEBUG]: Initialize FFTW with 8 threads.
pygmt-session [DEBUG]: GMT_Create_Session initialized GMT structure
pygmt-session [DEBUG]: Shared Library # 0 (core). Path = /Users/seisman/opt/GMT-debug/lib/libgmt.dylib
pygmt-session [DEBUG]: Loading GMT plugins from: /Users/seisman/opt/GMT-debug/lib/gmt/plugins
pygmt-session [DEBUG]: Shared Library # 1 (supplements). Path = /Users/seisman/opt/GMT-debug/lib/gmt/plugins/supplements.so
pygmt-session [DEBUG]: GMT now running in modern mode [Session ID = 61391]
pygmt-session [DEBUG]: GMT_Call_Command string: gmt figure d140f05165714c95a3a42cd454074ce1 -
pygmt-session [DEBUG]: Revised options: d140f05165714c95a3a42cd454074ce1 -
pygmt-session [DEBUG]: Exit:  gmt_reload_settings
pygmt-session [DEBUG]: Enter: gmtlib_plot_C_format
pygmt-session [DEBUG]: Exit:  gmtlib_plot_C_format
pygmt-session [DEBUG]: Enter: gmtinit_get_history
pygmt-session [DEBUG]: gmtlib_get_graphics_item: Fig: 1 Subplot: 2 Panel: () Inset: 0
pygmt-session [DEBUG]: Initialize FFTW with 8 threads.
pygmt-session [DEBUG]: GMT_Create_Session initialized GMT structure
pygmt-session [DEBUG]: Shared Library # 0 (core). Path = /Users/seisman/opt/GMT-debug/lib/libgmt.dylib
pygmt-session [DEBUG]: Loading GMT plugins from: /Users/seisman/opt/GMT-debug/lib/gmt/plugins
pygmt-session [DEBUG]: Shared Library # 1 (supplements). Path = /Users/seisman/opt/GMT-debug/lib/gmt/plugins/supplements.so
pygmt-session [DEBUG]: Pad argument (2) ignored in initialization of Data Table
pygmt-session [DEBUG]: Initializing a vector for handing external Input
pygmt-session [DEBUG]: Object ID 0 : Registered Vector Memory Reference 7fd069174830 as an Input resource with geometry Point [n_objects = 1]
pygmt-session [DEBUG]: Successfully created a new Vector container to represent a Data Table
pygmt-session [DEBUG]: Set_Object for family: 0
==> 1 API Objects at end of GMT_Create_Data
--------------------------------------------------------
K.. ID RESOURCE.... FAMILY.... ACTUAL.... DIR... S O M L
--------------------------------------------------------
* 0  0 7fd069174830 Data Table Vector     Input  0 Y N 0
--------------------------------------------------------
pygmt-session [DEBUG]: VirtualFile name created: @GMTAPI@-S-I-D-V-T-N-000000
pygmt-session [DEBUG]: GMT now running in modern mode [Session ID = 61391]
pygmt-session [DEBUG]: GMT_Call_Command string: gmt meca @GMTAPI@-S-I-D-V-T-N-000000 -JM5c -R-125/-122.25/46/48.5 -Sa.3
pygmt-session [DEBUG]: Use PS filename /Users/seisman/.gmt/sessions/gmt_session.61391/gmt_1.ps-
pygmt-session [DEBUG]: gmtinit_get_current_panel: No current panel selected so not in subplot mode
pygmt-session [DEBUG]: Revised options: @GMTAPI@-S-I-D-V-T-N-000000 -JM5c -R-125/-122.25/46/48.5 -Sa.3
meca [DEBUG]: History: Process -JM5c
meca [DEBUG]: History: Process -R-125/-122.25/46/48.5
meca [DEBUG]: Map distance calculation will be using great circle approximation with authalic auxiliary latitudes and authalic (R_2) radius = 6371007.1809 m, in meter.
meca [DEBUG]: Look for file -125/-122.25/46/48.5 in /Users/seisman/.gmt
meca [DEBUG]: Look for file -125/-122.25/46/48.5 in /Users/seisman/.gmt/cache
meca [DEBUG]: Look for file -125/-122.25/46/48.5 in /Users/seisman/.gmt/server
meca [DEBUG]: Got regular w/e/s/n for region (-125/-122.25/46/48.5)
meca [DEBUG]: Reset MAP_ANNOT_OBLIQUE to anywhere
meca [INFORMATION]: Central meridian not given, default to -123.625
meca [DEBUG]: Projected values in meters: -153064 153064 5.7496e+06 6.15843e+06
meca [DEBUG]: Computed automatic parameters using dimension scaling: 0.843708
meca [INFORMATION]: Map scale is 61.2257 km per cm or 1:6.12257e+06.
meca [DEBUG]: Running in PS mode modern
meca [DEBUG]: Use PS filename /Users/seisman/.gmt/sessions/gmt_session.61391/gmt_1.ps-
meca [DEBUG]: Create hidden PS file /Users/seisman/.gmt/sessions/gmt_session.61391/gmt_1.ps-
meca [DEBUG]: Got session name as pygmt-session and default graphics formats as pdf
meca [DEBUG]: Basemap order: Frame = above  Grid = below  Tick/Annot = below
meca [INFORMATION]: Linear magnitude scaling selected, normalizing by 5.
meca [DEBUG]: gmtapi_init_import: Passed family = Data Table and geometry = Point
meca (gmt_api.c:7824(gmtapi_init_import)): FYI: gmt_M_free given a NULL pointer - ignored
meca [DEBUG]: gmtapi_init_import: Added 1 new sources
meca [DEBUG]: GMT_Init_IO: Returned first Input object ID = 0
meca [DEBUG]: gmtapi_begin_io: Input resource access is now enabled [container]
meca [DEBUG]: gmtapi_import_dataset: Passed ID = -1 and mode = 0
meca [INFORMATION]: Referencing data table from user 7 column arrays of length 1
meca [DEBUG]: Object ID 1 : Registered Data Table Memory Reference 60000203ad00 as an Input resource with geometry Point [n_objects = 2]
meca [DEBUG]: gmtapi_import_dataset processed 1 resources
meca [DEBUG]: GMT_End_IO: Input resource access is now disabled
meca [DEBUG]: Set_Object for family: 6
==> 2 API Objects at end of GMT_Read_Data
--------------------------------------------------------
K.. ID RESOURCE.... FAMILY.... ACTUAL.... DIR... S O M L
--------------------------------------------------------
* 0  0 7fd069174830 Vector     Vector     Input  2 Y N 0
* 1  1 60000203ad00 Data Table Data Table Input  2 Y N 1
--------------------------------------------------------
meca [DEBUG]: GMT_End_IO: Input resource access is now disabled
meca [INFORMATION]: Number of records read: 1
meca [DEBUG]: Current size of half-baked PS file /Users/seisman/.gmt/sessions/gmt_session.61391/gmt_1.ps- = 22710.
==> 2 API Objects at end of GMTAPI_Garbage_Collection entry
--------------------------------------------------------
K.. ID RESOURCE.... FAMILY.... ACTUAL.... DIR... S O M L
--------------------------------------------------------
* 0  0 7fd069174830 Vector     Vector     Input  2 Y N 0
* 1  1 60000203ad00 Data Table Data Table Input  2 Y N 1
--------------------------------------------------------
meca [DEBUG]: gmtlib_garbage_collection: Destroying object: C=0 A=0 ID=1 W=Input F=Data Table M=Memory Reference S=Used P=60000203ad00 N=(null)
meca [DEBUG]: GMTAPI_Garbage_Collection freed 1 memory objects
meca [DEBUG]: gmtlib_unregister_io: Unregistering object no 1 [n_objects = 1]
==> 1 API Objects at end of GMTAPI_Garbage_Collection exit
--------------------------------------------------------
K.. ID RESOURCE.... FAMILY.... ACTUAL.... DIR... S O M L
--------------------------------------------------------
* 0  0 7fd069174830 Vector     Vector     Input  2 Y N 0
--------------------------------------------------------
python(61391,0x7ff85d8e6340) malloc: *** error for object 0x24bfb385c9b0: pointer being freed was not allocated
python(61391,0x7ff85d8e6340) malloc: *** set a breakpoint in malloc_error_break to debug
[1]    61391 abort      python test.py

@PaulWessel
Copy link
Member

I ran this via Xcode etc but no crash, at least it did not stop at a line like yours. It ended with these message:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/pwessel/UH/RESEARCH/CVSPROJECTS/GMTdev/pygmt/pygmt/helpers/decorators.py", line 598, in new_module
    return module_func(*args, **kwargs)
  File "/Users/pwessel/UH/RESEARCH/CVSPROJECTS/GMTdev/pygmt/pygmt/helpers/decorators.py", line 738, in new_module
    return module_func(*args, **kwargs)
  File "/Users/pwessel/UH/RESEARCH/CVSPROJECTS/GMTdev/pygmt/pygmt/src/meca.py", line 383, in meca
    lib.call_module(module="meca", args=build_arg_string(kwargs, infile=fname))
  File "/Users/pwessel/UH/RESEARCH/CVSPROJECTS/GMTdev/pygmt/pygmt/clib/session.py", line 621, in call_module
    raise GMTCLibError(
pygmt.exceptions.GMTCLibError: Module 'meca' failed with status code 45:

Unfortunately, if not crashing on macOS you may have to run in ddd in Linux...

@seisman
Copy link
Member

seisman commented Jun 19, 2023

Here are my understanding of the issue:

In PyGMT, we first call

GMT_Create_Data(API, GMT_IS_DATASET|GMT_VIA_VECTOR, GMT_IS_POINT, GMT_CONTAINER_ONLY, [7, 1, 1, 0], NULL, NULL, NULL, NULL, NULL)

to create the data container, and then call GMT_Put_Vectors and GMT_Put_Strings (family=GMT_IS_VECTOR|GMT_IS_DUPLICATE) to put the vectors/strings into the container. This creates the API object 0:

--------------------------------------------------------
K.. ID RESOURCE.... FAMILY.... ACTUAL.... DIR... S O M L
--------------------------------------------------------
* 0  0 7fd069174830 Vector     Vector     Input  2 Y N 0

Then in GMT, the psmeca module calls the GMT_Init_IO and GMT_Read_Data functions (L780 in psmeca.c https://github.com/GenericMappingTools/gmt/blob/8bf949a0ece1a3af56ba64e00cd979010d751854/src/seis/psmeca.c#L780). The GMT_Read_Data function calls gmtapi_import_dataset and then we go to the case GMT_IS_REFERENCE|GMT_VIA_VECTOR branch (https://github.com/GenericMappingTools/gmt/blob/8bf949a0ece1a3af56ba64e00cd979010d751854/src/gmt_api.c#L4091).

In the case GMT_IS_REFERENCE|GMT_VIA_VECTOR branch, the function creates a GMT_DATASET container and hooks up the vectors and the trailing text

...
S->data[col_pos_out] = V_obj->data[col_pos].f8;
SH->alloc_mode[col_pos_out] = GMT_ALLOC_EXTERNALLY;	
...
if (smode) S->text = V_obj->text;	/* Hook up trailing text array */

Now we have two API objects:

--------------------------------------------------------
K.. ID RESOURCE.... FAMILY.... ACTUAL.... DIR... S O M L
--------------------------------------------------------
* 0  0 7fd069174830 Vector     Vector     Input  2 Y N 0
* 1  1 60000203ad00 Data Table Data Table Input  2 Y N 1
--------------------------------------------------------

At the end of the psmeca module, we call the gmtlib_garbage_collection (and the gmtlib_free_dataset_ptr function) which frees the API object 1 (i.e., the Dataset container). The vector columns S->data[col] are not freed because alloc_mode[col] was set to GMT_ALLOC_EXTERNALLY, but the trailing text S->text are freed. It also frees the trailing texts of the original GMT_VECTOR object (i.e., V_obj->text) because S->text is a reference of V_obj->text.

Thus, at the end of the GMT session, when we try to free the API object 0 (i.e., V_obj->text), we see the pointer being freed was not allocated error.

I hope my understanding is correct and it can help you find a fix for this issue.

@PaulWessel
Copy link
Member

Hm, since the data columns have their flag

SH->alloc_mode[col_pos_out] = GMT_ALLOC_EXTERNALLY; /* Not this objects job to free what was passed in by reference */

it would seem we need a similar alloc_mode for the trailing text to protect it. In gmt_hidden.h the GMT_DATASEGMENT_HIDDEN struct for datasegments has

`enum GMT_enum_alloc *alloc_mode;	/* Allocation mode per column [GMT_ALLOC_INTERNALLY] */`

So I will add

`enum GMT_enum_alloc alloc_mode_text;	/* Allocation mode for trailing text [GMT_ALLOC_INTERNALLY] */`

and then consult this variable before free. Sees sensible?

@seisman
Copy link
Member

seisman commented Jun 19, 2023

So I will add

`enum GMT_enum_alloc alloc_mode_text;	/* Allocation mode for trailing text [GMT_ALLOC_INTERNALLY] */`

and then consult this variable before free. Sees sensible?

Yes, it will very likely fix the issue!

PaulWessel added a commit to GenericMappingTools/gmt that referenced this issue Jun 19, 2023
See GenericMappingTools/pygmt#2524 for background.  Sees we are trying to free strings thar belong to Python and not GMT.  However, not solved yet.
@seisman seisman added the upstream Bug or missing feature of upstream core GMT label Jun 19, 2023
@PaulWessel
Copy link
Member

Not so. And, if I try to place a stop point in psmeca it never stops there, It stops in the places I asked (Put_Strings etc in the API) but pretty soon we are in the GarbageCollector and no evidence it ever went into meta. Not sure what to do.

@seisman
Copy link
Member

seisman commented Jun 19, 2023

Your changes in PR GenericMappingTools/gmt#7557 work well for me after applying the changes in https://github.com/GenericMappingTools/gmt/pull/7557/files#r1234079875.

@seisman seisman added this to the 0.10.0 milestone Jun 22, 2023
PaulWessel added a commit to GenericMappingTools/gmt that referenced this issue Jun 22, 2023
* Do no free external trailing text strings

See GenericMappingTools/pygmt#2524 for background.  Sees we are trying to free strings thar belong to Python and not GMT.  However, not solved yet.

* Update gmt_io.c

* Update src/gmt_io.c

Co-authored-by: Dongdong Tian <[email protected]>

---------

Co-authored-by: Dongdong Tian <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working upstream Bug or missing feature of upstream core GMT
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants