Skip to content

Segmentation fault at garbage collection after running ab09nd with return value of nr=0 #242

Description

@mccullerlp

I'm using ab09nd to reduce systems. Mildly by accident we are putting in a large system and choosing inputs/outputs that don't touch any of the dynamics. The function correctly reduces the system to size zero on output, but for some reason this now causes a segmentation fault.

I've compiled Slycot with -fcheck=all -fbacktrace -Og -g -Wall, but the segfault only occurs after garbage collection, and will occur immediately if you force collection using 'import gc; gc.collect()'

somehow this output case needs to be handled better by f2py or the wrapper instructions.

Attached is a yaml file with the system A,B,C,D that triggers the bug when run with dico = 'C', job = 'B', equil = 'S'

debug_ab09nd.txt

Activity

  1. roryyorke commented on Dec 22, 2024

    @roryyorke
    Collaborator

    Thanks for the report.

    On Debian 12 system running on x86_64 system via WSL, with the script below I get munmap_chunk(): invalid pointer on system exit after running this code. The same thing happens if ab09nd is only called once, and the gc.collect call is omitted. Differently from the report, I don't get a segfault the instant gc.collect() is called, but not sure that is really significant.

    This Slycot 0.6.0 installed from conda-forge.

    I've attached the conda environment file, though not it's not minimal since I installed jupyterlab to investigate.

    Output:

    slycot.__version__='0.6.0'
    i=0 nr=0 gc.collect()=0
    i=1 nr=0 gc.collect()=0
    done
    munmap_chunk(): invalid pointer
    Aborted (core dumped)
    

    Script:

    import gc
    
    import numpy as np
    import slycot
    import yaml
    
    print(f'{slycot.__version__=}')
    
    for i in range(2):
        with open('debug_ab09nd.txt') as infile:
            problem = yaml.load(infile, yaml.Loader)
    
        a = np.array(problem['A'])
        b = np.array(problem['B'])
        c = np.array(problem['C'])
        d = np.array(problem['D'])
    
        nr, ar, br, cr, dr, ns, hsv = \
            slycot.ab09nd(dico='C', job='B', equil='S', n=a.shape[0],
                          m=b.shape[1], p=c.shape[0], A=a, B=b, C=c, D=d)
    
        print(f'{i=} {nr=} {gc.collect()=}')
    
    
    print('done')
    
  2. roryyorke commented on Dec 22, 2024

    @roryyorke
    Collaborator
  3. bnavigator commented on Dec 22, 2024

    @bnavigator
    Collaborator

    Thanks @roryyorke. I can reproduce on openSUSE Tumbleweed with the system package python311-slycot 0.6.0-1.3.

    So that rules out the conda-forge build being significant.

  4. roryyorke commented on Dec 23, 2024

    @roryyorke
    Collaborator

    this seems to fix it

    modified   slycot/src/analysis.pyf
    @@ -315,7 +315,7 @@ subroutine ab09nd(dico,job,equil,ordsel,n,m,p,nr,alpha,a,lda,b,ldb,c,ldc,d,ldd,n
         double precision intent(out),dimension(n),depend(n) :: hsv
         double precision :: tol1 =0.0
         double precision :: tol2 =0.0
    -    integer intent(hide,cache),dimension(max(m,p)) :: iwork
    +    integer intent(hide,cache),dimension(max(1,2*n)) :: iwork
         double precision intent(hide,cache),dimension(ldwork) :: dwork
         integer optional :: ldwork = max(1,n*(2*n+max(n,max(m,p))+5)+n*(n+1)/2)
         integer intent(out) :: iwarn
    

    compare with doc for AB09ND.f comment, fairly sure iwork calc is a bug:

    C     Workspace
    C
    C     IWORK   INTEGER array, dimension (MAX(1,2*N))
    C             On exit, if INFO = 0, IWORK(1) contains the order of the
    C             minimal realization of the ALPHA-stable part of the
    C             system.
    C
    
  5. roryyorke commented on Dec 23, 2024

    @roryyorke
    Collaborator

    here's a simpler reproducer, on which I'll base a unit test. The much-too-small iwork means AB09ND stomps all over the stack, giving wrong dr, and ultimately breaks everything.

    Program:

    import gc
    
    import numpy as np
    import slycot
    import yaml
    
    n = 67
    m = 1
    p = 1
    
    a = -np.eye(n)
    b = np.zeros((n, m))
    c = np.zeros((p, n))
    d = np.array([[42.24]])
    
    nr, ar, br, cr, dr, ns, hsv = \
        slycot.ab09nd(dico='C', job='B', equil='S', n=a.shape[0],
                      m=b.shape[1], p=c.shape[0], A=a, B=b, C=c, D=d)
    
    print(f'{nr=}, {dr=}')
    

    Result pre-fix:

    $ python repro_simple.py
    nr=0, dr=array([[1.0609979e-312]])
    munmap_chunk(): invalid pointer
    Aborted (core dumped)
    

    Post-fix:

    $ python repro_simple.py
    nr=0, dr=array([[42.24]])
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions