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 when calling Julia functions #183

Closed
veddox opened this issue Oct 10, 2023 · 8 comments
Closed

Segfault when calling Julia functions #183

veddox opened this issue Oct 10, 2023 · 8 comments

Comments

@veddox
Copy link

veddox commented Oct 10, 2023

When my QML window calls a function that was defined in Julia and tagged using @qmlfunction, I get a segfault:

[132030] signal (11.1): Segmentation fault
in expression starting at [...]/run.jl:13
_ZN7qmlwrap8JuliaAPI13set_js_engineEP9QJSEngine at ~/.julia/artifacts/5b399b8a0d2ef4ba00667e41a3fe59db6eaa6000/lib/libjlqml.so (unknown line)

It seems that libjlqml is not installed - how can I do so? Edit: I manually installed jlqml_jll 0.5.3, but the error persists.

I'm using QML.jl 0.8 with Qt6Base_jll 6.5.2 and CxxWrap 0.14.0 on Julia 1.9.3. Is there any other dependency I need?

@veddox veddox changed the title Segfault when calling Julia functions - missing libjlqml? Segfault when calling Julia functions Oct 10, 2023
@veddox
Copy link
Author

veddox commented Oct 10, 2023

I get the same segfault when running the code example at the @qmlfunction documentation:

julia> using QML

julia> greet() = "Hello, World!";

julia> @qmlfunction greet

julia> mktempdir() do folder
          path = joinpath(folder, "main.qml")
          write(path, """
          import org.julialang
          import QtQuick
          import QtQuick.Controls
          ApplicationWindow {
            visible: true
            Text {
              text: Julia.greet()
            }
            Timer {
              running: true; repeat: false
              onTriggered: Qt.exit(0)
            }
          }
          """)
          loadqml(path)
          exec()
        end

@veddox
Copy link
Author

veddox commented Oct 10, 2023

I get the same segfault when running the code example at the @qmlfunction documentation

This just got a bit weirder. I realised that the above statement is not strictly true. As long as I call @qmlfunction greet every time before executing the do block, it works. If I call the do block twice in succession, it segfaults.

The error seems to be in this function in jlqml_jll, but I don't understand the code well enough to see it.

@veddox
Copy link
Author

veddox commented Oct 10, 2023

Working through the code of julia_api.cpp a bit more, I found the following line:

  s_singletonInstance->set_js_engine(qmlEngine);

Shouldn't this pass scriptEngine rather than qmlEngine?

@barche
Copy link
Collaborator

barche commented Oct 10, 2023

Thanks for reporting this and looking into it. The reason is that after exec has returned the internal Qt state is cleaned up completely, and the functions are no longer registered. So inded, you have to call @qmlfunction again before exec, but a segfault probably isn't the most user friendly way of communicating this, so that needs to be fixed.

@veddox
Copy link
Author

veddox commented Oct 11, 2023

Wonderful, thank you for addressing this so quickly!

However, I don't yet understand how this affects my original problem. Why do I get this segfault straight away when running my own code?

This is the file in question (redacted, but structurally unchanged):

global model = missing
const running = Observable(false)
const date = Observable(today())
const progress = Observable(0.0)
const delay = Observable(0.5)
const runbuttontext = Observable(">>")
const runbuttontip = Observable("Run")

function newsimulation()
    # do some stuff
    println("Model initialised.")
end

function nextstep()
    # do some stuff
    println("Updated model.")
end

function runsimulation()
    # do some stuff
end

function togglerunning()
    if running[]
        running[] = false
        runbuttontext[] = ">>"
        runbuttontip[] = "Run"
    else
        running[] = true
        runbuttontext[] = "||"
        runbuttontip[] = "Pause"
        runsimulation()
    end
end

function render_map(screen)
    # do some stuff
end

@qmlfunction newsimulation
@qmlfunction nextstep
@qmlfunction togglerunning
@qmlfunction render_map

on(delay) do d
    println("Delay is now $(round(d, digits=1)) seconds.")
end

on(running) do r
    r ? println("Simulation started.") : println("Simulation stopped.")
end

"""
    launch()

The main function that creates the application.
"""
function launch()
    qmlfile = joinpath(dirname(@__FILE__), "main.qml")
    loadqml(qmlfile,
            vars = JuliaPropertyMap("running" => running,
                                    "date" => date,
                                    "delay" => delay,
                                    "progress" => progress,
                                    "runbuttontext" => runbuttontext,
                                    "runbuttontip" => runbuttontip))
    println("Launched program.")
    exec()
end

When I load my package and run launch(), it segfaults immediately. It also crashes when I load the package but then manually execute loadqml() and exec().

barche added a commit to JuliaGraphics/jlqml that referenced this issue Oct 11, 2023
barche added a commit to JuliaGraphics/jlqml that referenced this issue Oct 14, 2023
@ufechner7 ufechner7 added this to the 0.8.1 milestone Oct 14, 2023
barche added a commit to JuliaGraphics/jlqml that referenced this issue Oct 15, 2023
barche added a commit that referenced this issue Oct 16, 2023
Issue Properties passed to `loadqml` makes app to crash when loaded from module #165
Issue Segfault when calling Julia functions #183
@barche
Copy link
Collaborator

barche commented Oct 16, 2023

Fixed in QML.jl 0.8.1, with documentation here: https://juliagraphics.github.io/QML.jl/dev/#Using-QML.jl-inside-another-Julia-module

@barche barche closed this as completed Oct 16, 2023
@ufechner7
Copy link
Member

Wonderful, thank you for addressing this so quickly!

However, I don't yet understand how this affects my original problem. Why do I get this segfault straight away when running my own code?

This is the file in question (redacted, but structurally unchanged):

global model = missing
const running = Observable(false)
const date = Observable(today())
const progress = Observable(0.0)
const delay = Observable(0.5)
const runbuttontext = Observable(">>")
const runbuttontip = Observable("Run")

function newsimulation()
    # do some stuff
    println("Model initialised.")
end

function nextstep()
    # do some stuff
    println("Updated model.")
end

function runsimulation()
    # do some stuff
end

function togglerunning()
    if running[]
        running[] = false
        runbuttontext[] = ">>"
        runbuttontip[] = "Run"
    else
        running[] = true
        runbuttontext[] = "||"
        runbuttontip[] = "Pause"
        runsimulation()
    end
end

function render_map(screen)
    # do some stuff
end

@qmlfunction newsimulation
@qmlfunction nextstep
@qmlfunction togglerunning
@qmlfunction render_map

on(delay) do d
    println("Delay is now $(round(d, digits=1)) seconds.")
end

on(running) do r
    r ? println("Simulation started.") : println("Simulation stopped.")
end

"""
    launch()

The main function that creates the application.
"""
function launch()
    qmlfile = joinpath(dirname(@__FILE__), "main.qml")
    loadqml(qmlfile,
            vars = JuliaPropertyMap("running" => running,
                                    "date" => date,
                                    "delay" => delay,
                                    "progress" => progress,
                                    "runbuttontext" => runbuttontext,
                                    "runbuttontip" => runbuttontip))
    println("Launched program.")
    exec()
end

When I load my package and run launch(), it segfaults immediately. It also crashes when I load the package but then manually execute loadqml() and exec().

Is this still an issue with QML 0.8.1?

@veddox
Copy link
Author

veddox commented Oct 17, 2023

Is this still an issue with QML 0.8.1?

No. Bart and I had a short video conference yesterday and it works now 🙂

One problem had been that I was calling @qmlfunction outside of the launch() function. The other problem was the QML module lookup bug, which is fixed now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants