Interesting problem for Crystal developers (Stack overflow)

Hi, today I was continuing my project made in Crystal.
After I fixed an error in my code, I had this bug.

I think it can be interesting for the crystal developers, because this output can’t found the problem:

This the related portion code I fixed:

def writeSettingsFile
            settings = Settings.new(@rootPath,
                                    @systemName,
                                    @targetName,
                                    @architecture,
                                    @target,
                                    @makeOptions,
                                    @buildOptions,
                                    @installByChroot,
                                    @chrootSystemName,
                                    @chrootTargetName,
                                    @chrootArchitecture,
                                    @chrootTarget,
                                    @chrootMakeOptions,
                                    @chrootBuildOptions)

            file = File.open("/"+ISM::Default::CommandLineSettings::SettingsFilePath,"w")
            settings.to_json(file)
            file.close

            if Ism.settings.rootPath != "/"
                chrootFile = File.open(Ism.settings.rootPath+ISM::Default::CommandLineSettings::SettingsFilePath,"w")

                chrootSettings = Settings.new(  ISM::Default::CommandLineSettings::RootPath,
                                                @chrootSystemName,
                                                @chrootTargetName,
                                                @chrootArchitecture,
                                                @chrootTarget,
                                                @chrootMakeOptions,
                                                @chrootBuildOptions,
                                                ISM::Default::CommandLineSettings::InstallByChroot,
                                                ISM::Default::CommandLineSettings::SystemName,
                                                ISM::Default::CommandLineSettings::TargetName,
                                                ISM::Default::CommandLineSettings::Architecture,
                                                ISM::Default::CommandLineSettings::Target,
                                                ISM::Default::CommandLineSettings::MakeOptions,
                                                ISM::Default::CommandLineSettings::BuildOptions)
                chrootSettings.to_json(chrootFile)

                chrootFile.close
            end
        end

The error I had before I fixed it:

zohran@alienware-m17-r3 ~/Documents/Programmation/ISM $ crystal build Main.cr -o ism
Showing last frame. Use --error-trace for full trace.

In ISM/CommandLineSettings.cr:90:43

 90 | chrootSettings = Settings.new
                                ^--
Error: wrong number of arguments for 'ISM::CommandLineSettings::Settings.new' (given 0, expected 1, 14)

Overloads are:
 - ISM::CommandLineSettings::Settings.new(rootPath : String, systemName : String, targetName : String, architecture : String, target : String, makeOptions : String, buildOptions : String, installByChroot : Bool, chrootSystemName : String, chrootTargetName : String, chrootArchitecture : String, chrootTarget : String, chrootMakeOptions : String, chrootBuildOptions : String)
 - ISM::CommandLineSettings::Settings.new(pull : ::JSON::PullParser)

After I fixed it (I didn’t put all of the log, it’s too long):

zohran@alienware-m17-r3 ~/Documents/Programmation/ISM $ 
crystal build Main.cr -o ism
Stack overflow (e.g., infinite or very deep recursion)
[0x562c0896ecf6] ?? +94747122658550 in crystal
[0x562c0896ec84] ?? +94747122658436 in crystal
[0x7f268bcc8a90] ?? +139803530922640 in /lib64/libc.so.6
[0x562c0855d875] ?? +94747118393461 in crystal
[0x562c0854e556] ?? +94747118331222 in crystal
[0x562c0854e29f] ?? +94747118330527 in crystal
[0x562c0854e48e] ?? +94747118331022 in crystal
[0x562c0855d170] ?? +94747118391664 in crystal
[0x562c0854e556] ?? +94747118331222 in crystal
[0x562c0854e29f] ?? +94747118330527 in crystal
[0x562c0854e48e] ?? +94747118331022 in crystal
[0x562c0855d170] ?? +94747118391664 in crystal
[0x562c0854e556] ?? +94747118331222 in crystal
[0x562c0854e29f] ?? +94747118330527 in crystal
[0x562c0854e48e] ?? +94747118331022 in crystal
[0x562c0855d170] ?? +94747118391664 in crystal

If you need, this is the full file of the implemented class:

module ISM

    class CommandLineSettings

        record Settings,
            rootPath : String,
            systemName : String,
            targetName : String,
            architecture : String,
            target : String,
            makeOptions : String,
            buildOptions : String,
            installByChroot : Bool,
            chrootSystemName : String,
            chrootTargetName : String,
            chrootArchitecture : String,
            chrootTarget : String,
            chrootMakeOptions : String,
            chrootBuildOptions : String do
            include JSON::Serializable
        end

        property    rootPath : String
        property    installByChroot : Bool
        property    chrootSystemName : String
        property    chrootTargetName : String
        property    chrootArchitecture : String
        property    chrootTarget : String
        property    chrootMakeOptions : String
        property    chrootBuildOptions : String

        def initialize( @rootPath = ISM::Default::CommandLineSettings::RootPath,
                        @systemName = ISM::Default::CommandLineSettings::SystemName,
                        @targetName = ISM::Default::CommandLineSettings::TargetName,
                        @architecture = ISM::Default::CommandLineSettings::Architecture,
                        @target = ISM::Default::CommandLineSettings::Target,
                        @makeOptions = ISM::Default::CommandLineSettings::MakeOptions,
                        @buildOptions = ISM::Default::CommandLineSettings::BuildOptions,
                        @installByChroot = ISM::Default::CommandLineSettings::InstallByChroot,
                        @chrootSystemName = ISM::Default::CommandLineSettings::ChrootSystemName,
                        @chrootTargetName = ISM::Default::CommandLineSettings::ChrootTargetName,
                        @chrootArchitecture = ISM::Default::CommandLineSettings::ChrootArchitecture,
                        @chrootTarget = ISM::Default::CommandLineSettings::ChrootTarget,
                        @chrootMakeOptions = ISM::Default::CommandLineSettings::ChrootMakeOptions,
                        @chrootBuildOptions = ISM::Default::CommandLineSettings::ChrootBuildOptions)
        end

        def loadSettingsFile
            information = Settings.from_json(File.read("/"+ISM::Default::CommandLineSettings::SettingsFilePath))
      
            @rootPath = information.rootPath
            @systemName = information.systemName
            @targetName = information.targetName
            @architecture = information.architecture
            @target = information.target
            @makeOptions = information.makeOptions
            @buildOptions = information.buildOptions
            @installByChroot = information.installByChroot
            @chrootSystemName = information.chrootSystemName
            @chrootTargetName = information.chrootTargetName
            @chrootArchitecture = information.chrootArchitecture
            @chrootTarget = information.chrootTarget
            @chrootMakeOptions = information.chrootMakeOptions
            @chrootBuildOptions = information.chrootBuildOptions
        end

        def writeSettingsFile
            settings = Settings.new(@rootPath,
                                    @systemName,
                                    @targetName,
                                    @architecture,
                                    @target,
                                    @makeOptions,
                                    @buildOptions,
                                    @installByChroot,
                                    @chrootSystemName,
                                    @chrootTargetName,
                                    @chrootArchitecture,
                                    @chrootTarget,
                                    @chrootMakeOptions,
                                    @chrootBuildOptions)

            file = File.open("/"+ISM::Default::CommandLineSettings::SettingsFilePath,"w")
            settings.to_json(file)
            file.close

            if Ism.settings.rootPath != "/"
                chrootFile = File.open(Ism.settings.rootPath+ISM::Default::CommandLineSettings::SettingsFilePath,"w")

                chrootSettings = Settings.new(  ISM::Default::CommandLineSettings::RootPath,
                                                @chrootSystemName,
                                                @chrootTargetName,
                                                @chrootArchitecture,
                                                @chrootTarget,
                                                @chrootMakeOptions,
                                                @chrootBuildOptions,
                                                ISM::Default::CommandLineSettings::InstallByChroot,
                                                ISM::Default::CommandLineSettings::SystemName,
                                                ISM::Default::CommandLineSettings::TargetName,
                                                ISM::Default::CommandLineSettings::Architecture,
                                                ISM::Default::CommandLineSettings::Target,
                                                ISM::Default::CommandLineSettings::MakeOptions,
                                                ISM::Default::CommandLineSettings::BuildOptions)
                chrootSettings.to_json(chrootFile)

                chrootFile.close
            end
        end

        def systemName : String
            return (Ism.settings.rootPath != "/" ? @chrootSystemName : @systemName)
        end

        def targetName : String
            return (Ism.settings.rootPath != "/" ? @chrootTargetName : @targetName)
        end

        def architecture : String
            return (Ism.settings.rootPath != "/" ? @chrootArchitecture : @architecture)
        end

        def target : String
            return (Ism.settings.rootPath != "/" ? @chrootTarget : @target)
        end

        def makeOptions : String
            return (Ism.settings.rootPath != "/" ? @chrootMakeOptions : @makeOptions)
        end

        def buildOptions : String
            return (Ism.settings.rootPath != "/" ? @chrootBuildOptions : @buildOptions)
        end

        def setRootPath(@rootPath)
            writeSettingsFile
        end

        def setSystemName(@systemName)
            writeSettingsFile
        end

        def setTargetName(@targetName)
            writeSettingsFile
            setTarget
        end

        def setArchitecture(@architecture)
            writeSettingsFile
            setTarget
        end

        def setTarget
            @target = @architecture + "-" + @targetName + "-" + "linux-gnu"
            writeSettingsFile
        end

        def setMakeOptions(@makeOptions)
            writeSettingsFile
        end

        def setBuildOptions(@buildOptions)
            writeSettingsFile
        end

        def setInstallByChroot(@installByChroot)
            writeSettingsFile
        end

        def setChrootSystemName(@chrootSystemName)
            writeSettingsFile
        end

        def setChrootTargetName(@chrootTargetName)
            writeSettingsFile
        end

        def setChrootArchitecture(@chrootArchitecture)
            writeSettingsFile
        end

        def setChrootTarget(@chrootTarget)
            writeSettingsFile
        end

        def setChrootMakeOptions(@chrootMakeOptions)
            writeSettingsFile
        end

        def setChrootBuildOptions(@chrootBuildOptions)
            writeSettingsFile
        end


        def temporaryPath
            return "#{@rootPath}#{ISM::Default::Path::TemporaryDirectory}"
        end

        def sourcesPath
            return "#{@rootPath}#{ISM::Default::Path::SourcesDirectory}"
        end

        def toolsPath
            return "#{@rootPath}#{ISM::Default::Path::ToolsDirectory}"
        end

    end

end

And the full project repository: GitHub - Fulgurance/ISM: Ingenius System Manager

I did a test to simply in the function

writeSettingsFile

by doing by replacement

chrootSettings = settings

Because I never had problem with the settings variable, but I have again a stack overflow.
The problem come with this chrootSettings assignment

Hm, I’m not really seeing what could cause an infinite loop, but assuming it’s passing through the writeSettingsFile that you updated, you could use the caller method to try and track down the loop. I’ve done:

puts caller.join("\n\t")

To find this kind of stuff before. If you’re on windows (based on the Documents file path), you might need to join with "\r\n\t" for better formatting.

1 Like

Arf shame on me, I understood the problem.

This is the problem of copy/past…

module ISM

    module Default

        module CommandLineSettings

            RootPath = "/"
            SystemName = "Unknow"
            TargetName = "unknow"
            Architecture = "x86_64"
            Target = "#{Architecture}-#{TargetName}-linux-gnu"
            MakeOptions = "-j1"
            BuildOptions = "-march=native -O2 -pipe"
            InstallByChroot = false
            ChrootSystemName = "#{SystemName}"
            ChrootTargetName = "#{ChrootTargetName}"
            ChrootArchitecture = "#{ChrootArchitecture}"
            ChrootTarget = "#{ChrootTarget}"
            ChrootMakeOptions = "#{ChrootMakeOptions}"
            ChrootBuildOptions = "#{ChrootBuildOptions}"
            SettingsFilePath = "#{ISM::Default::Path::SettingsDirectory}#{ISM::Default::Filename::Settings}"


        end

    end

end

Of course I have an infinite loop :smiling_face_with_tear:

Huh, thought the compiler would prevent that :P Glad it’s fixed!

Yeah sorry for that.

Fortunately I coded already in assembly, so generally I can imagine quickly the problem

I’m not sure but I feel the last crystal version check less things. Now when I test my program, the execution continue, even there is a bug, is it normal ?