FFTW plan gets clobbered when module is compiled

I have a function that calls fft() repeatedly. For performance I implemented an FFT plan. In some situations the length of data will remain the same, in other cases the the length changes. For this reason the plan is a global variable so that the previous plan is accessible if the data length is the same.

My working code is in a module. When it is stepped through outside of the module it works correctly. When using the module

using ModuleName

the plan seems to get clobbered. With @infiltrate stopping execution and then typing the name of the plan in the REPL, Julia crashes into the OS.

Example code that works without problem is shown below where foo() is executed.

using FFTW

plan::FFTW.cFFTWPlan{ComplexF64, -1, false, 1, UnitRange{Int64}} = plan_fft(rand(ComplexF64, 10), flags=FFTW.ESTIMATE)
iplan::AbstractFFTs.ScaledPlan{ComplexF64, FFTW.cFFTWPlan{ComplexF64, 1, false, 1, UnitRange{Int64}}, Float64} = 

function si(data, plan, iplan)
    f = plan * data
    datam = iplan * f

function bar(data)
    oldplanlength = parse(Int, split(string(plan), [' ', '-'])[5])
    if length(data) != oldplanlength
        global plan = plan_fft(copy(data), flags=FFTW.MEASURE, timelimit=1)
        global iplan = inv(plan)
    v = si(data, plan, iplan)
    return v

function foo()
    for l in range(10^5, length=3)
        data = rand(l)
        datam = bar(data)
        println(data ≈ datam)

This code was also wrapped in a module and it still worked.

The error message from the crash in the implemented program is as follows:

length(data) = 6548297
┌ Debug: 6548297
└ @ CatawbaWinder03 C:\Users\jakez\.julia\dev\CatawbaWinder03\src\predictivemaintenance.jl:184

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x721e0d7 -- .text at C:\Users\jakez\.julia\artifacts\b7dd1809d0626eac3bf6f97ba8ccfbb6cc63c509\bin\libfftw3-3.dll (unknown line)
in expression starting at REPL[3]:1
.text at C:\Users\jakez\.julia\artifacts\b7dd1809d0626eac3bf6f97ba8ccfbb6cc63c509\bin\libfftw3-3.dll (unknown line)
sprint_plan_ at C:\Users\jakez\.julia\packages\FFTW\pSlmu\src\fft.jl:428 [inlined]
sprint_plan at C:\Users\jakez\.julia\packages\FFTW\pSlmu\src\fft.jl:433 [inlined]
show at C:\Users\jakez\.julia\packages\FFTW\pSlmu\src\fft.jl:446
print at .\strings\io.jl:35
print_to_string at .\strings\io.jl:144
string at .\strings\io.jl:185 [inlined]
macro expansion at .\show.jl:1128 [inlined]
macro expansion at .\logging.jl:360 [inlined]
predictivemaintenance at C:\Users\jakez\.julia\dev\CatawbaWinder03\src\predictivemaintenance.jl:185
unknown function (ip: 000001440ff9be56)
autorun at C:\Users\jakez\.julia\dev\CatawbaWinder03\src\CatawbaWinder03.jl:154
unknown function (ip: 0000014449dd8413)
jl_apply at C:/workdir/src\julia.h:1878 [inlined]
do_call at C:/workdir/src\interpreter.c:126
eval_value at C:/workdir/src\interpreter.c:226
eval_stmt_value at C:/workdir/src\interpreter.c:177 [inlined]
eval_body at C:/workdir/src\interpreter.c:624
jl_interpret_toplevel_thunk at C:/workdir/src\interpreter.c:762
jl_toplevel_eval_flex at C:/workdir/src\toplevel.c:912
jl_toplevel_eval_flex at C:/workdir/src\toplevel.c:856
jl_toplevel_eval_flex at C:/workdir/src\toplevel.c:856
jl_toplevel_eval_flex at C:/workdir/src\toplevel.c:856
ijl_toplevel_eval at C:/workdir/src\toplevel.c:921 [inlined]
ijl_toplevel_eval_in at C:/workdir/src\toplevel.c:971
eval at .\boot.jl:370 [inlined]
eval_user_input at C:\workdir\usr\share\julia\stdlib\v1.9\REPL\src\REPL.jl:153
repl_backend_loop at C:\workdir\usr\share\julia\stdlib\v1.9\REPL\src\REPL.jl:249
#start_repl_backend#46 at C:\workdir\usr\share\julia\stdlib\v1.9\REPL\src\REPL.jl:234
start_repl_backend at C:\workdir\usr\share\julia\stdlib\v1.9\REPL\src\REPL.jl:231
#run_repl#59 at C:\workdir\usr\share\julia\stdlib\v1.9\REPL\src\REPL.jl:377
run_repl at C:\workdir\usr\share\julia\stdlib\v1.9\REPL\src\REPL.jl:363
jfptr_run_repl_60953.clone_1 at C:\Users\jakez\AppData\Local\Programs\Julia-1.9.0-rc1\lib\julia\sys.dll (unknown line)
#1017 at .\client.jl:421
jfptr_YY.1017_30627.clone_1 at C:\Users\jakez\AppData\Local\Programs\Julia-1.9.0-rc1\lib\julia\sys.dll (unknown line)
jl_apply at C:/workdir/src\julia.h:1878 [inlined]
jl_f__call_latest at C:/workdir/src\builtins.c:774
#invokelatest#2 at .\essentials.jl:816 [inlined]
invokelatest at .\essentials.jl:813 [inlined]
run_main_repl at .\client.jl:405
exec_options at .\client.jl:322
_start at .\client.jl:522
jfptr__start_54005.clone_1 at C:\Users\jakez\AppData\Local\Programs\Julia-1.9.0-rc1\lib\julia\sys.dll (unknown line)
jl_apply at C:/workdir/src\julia.h:1878 [inlined]
true_main at C:/workdir/src\jlapi.c:573
jl_repl_entrypoint at C:/workdir/src\jlapi.c:717
mainCRTStartup at C:/workdir/cli\loader_exe.c:59
BaseThreadInitThunk at C:\WINDOWS\System32\KERNEL32.DLL (unknown line)
RtlUserThreadStart at C:\WINDOWS\SYSTEM32\ntdll.dll (unknown line)
Allocations: 768134385 (Pool: 768048716; Big: 85669); GC: 620
PS C:\Users\jakez\.julia\dev\CatawbaWinder03\src>

I am sorry that with many attempts I have not been able to get a MWE to exhibit this behaviour. I am hoping that someone may be able to see what the problem is.

1 Like

The plan contains a raw pointer to a C data structure in FFTW. If you are using a module in a package, so that it’s precompiled, then the pointer is saved during precompilation but when the module is loaded it no longer points to valid memory.

If you want to initialize global plans in a module, you’ll need to initialize them in the module’s __init__ function so that they are initialized/re-created every time the module is loaded.