Skip to content

Commit

Permalink
Merge branch 'master' into messaging-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
halleysfifthinc authored Jan 29, 2025
2 parents f63ccfb + 2164bfc commit 57df15d
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 16 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ jobs:
- os: ubuntu-latest
julia-arch: x86
julia-version: '1'

steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.julia-version }}
arch: ${{ matrix.julia-arch }}
- uses: julia-actions/cache@v1
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v5
with:
files: lcov.info
token: ${{ secrets.CODECOV_TOKEN }}
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ Conda = "1"
JSON = "0.18,0.19,0.20,0.21,1"
MbedTLS = "0.5,0.6,0.7,1"
SoftGlobalScope = "1"
ZMQ = "1"
ZMQ = "1.3"
julia = "1.10"
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ If you already have Python/Jupyter installed on your machine, this process will
that tells Jupyter how to launch Julia. You can then launch the notebook server the usual
way by running `jupyter notebook` in the terminal.

Note that `IJulia` should generally be installed in Julia's global package environment, unless you
install a custom kernel that specifies a particular environment.

Alternatively, you can have IJulia create and manage its own Python/Jupyter installation.
To do this, type the following in Julia, at the `julia>` prompt:

Expand Down
12 changes: 11 additions & 1 deletion deps/kspec.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,16 @@ else
exe(s::AbstractString, e::AbstractString) = s * e
end

function display_name(name::AbstractString)
debugdesc = ccall(:jl_is_debugbuild,Cint,())==1 ? "-debug" : ""
return name * " " * Base.VERSION_STRING * debugdesc
end

"""
installkernel(name::AbstractString, options::AbstractString...;
julia::Cmd,
specname::AbstractString,
displayname::AbstractString,
env=Dict())
Install a new Julia kernel, where the given `options` are passed to the `julia`
Expand All @@ -71,6 +77,9 @@ kernelpath = installkernel("Julia O3", "-O3", env=Dict("FOO"=>"yes"))
creates a new Julia kernel in which `julia` is launched with the `-O3`
optimization flag and `FOO=yes` is included in the environment variables.
The `displayname` argument can be used to customize the name displayed in the
Jupyter kernel list.
The returned `kernelpath` is the path of the installed kernel directory,
something like `/...somepath.../kernels/julia-o3-1.6` (in Julia 1.6). The
`specname` argument can be passed to alter the name of this directory (which
Expand All @@ -96,6 +105,7 @@ installkernel(
function installkernel(name::AbstractString, julia_options::AbstractString...;
julia::Cmd = `$(joinpath(Sys.BINDIR,exe("julia")))`,
specname::AbstractString = kernelspec_name(name),
displayname::AbstractString = display_name(name),
env::Dict{<:AbstractString}=Dict{String,Any}())
# Is IJulia being built from a debug build? If so, add "debug" to the description.
debugdesc = ccall(:jl_is_debugbuild,Cint,())==1 ? "-debug" : ""
Expand All @@ -112,7 +122,7 @@ function installkernel(name::AbstractString, julia_options::AbstractString...;

ks = Dict(
"argv" => kernelcmd_array,
"display_name" => name * " " * Base.VERSION_STRING * debugdesc,
"display_name" => displayname,
"language" => "julia",
"env" => env,
# Jupyter's signal interrupt mode is not supported on Windows
Expand Down
5 changes: 4 additions & 1 deletion src/handlers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,10 @@ function connect_request(socket, msg)
end

function shutdown_request(socket, msg)
send_ipython(socket, msg_reply(msg, "shutdown_reply",
# stop heartbeat thread by closing the context
close(heartbeat_context[])

send_ipython(requests[], msg_reply(msg, "shutdown_reply",
msg.content))
sleep(0.1) # short delay (like in ipykernel), to hopefully ensure shutdown_reply is sent
exit()
Expand Down
19 changes: 10 additions & 9 deletions src/heartbeat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
import Libdl

const threadid = zeros(Int, 128) # sizeof(uv_thread_t) <= 8 on Linux, OSX, Win
const zmq_proxy = Ref(C_NULL)

# entry point for new thread
function heartbeat_thread(sock::Ptr{Cvoid})
function heartbeat_thread(heartbeat::Ptr{Cvoid})
@static if VERSION v"1.9.0-DEV.1588" # julia#46609
# julia automatically "adopts" this thread because
# we entered a Julia cfunction. We then have to enable
Expand All @@ -19,14 +18,16 @@ function heartbeat_thread(sock::Ptr{Cvoid})
# (see julia#47196)
ccall(:jl_gc_safe_enter, Int8, ())
end
ccall(zmq_proxy[], Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}),
sock, sock, C_NULL)
nothing
ret = ZMQ.lib.zmq_proxy(heartbeat, heartbeat, C_NULL)
@static if VERSION v"1.9.0-DEV.1588" # julia#46609
# leave safe region if zmq_proxy returns (when context is closed)
ccall(:jl_gc_safe_leave, Int8, ())
end
return ret
end

function start_heartbeat(sock)
zmq_proxy[] = Libdl.dlsym(Libdl.dlopen(ZMQ.libzmq), :zmq_proxy)
heartbeat_c = @cfunction(heartbeat_thread, Cvoid, (Ptr{Cvoid},))
function start_heartbeat(heartbeat)
heartbeat_c = @cfunction(heartbeat_thread, Cint, (Ptr{Cvoid},))
ccall(:uv_thread_create, Cint, (Ptr{Int}, Ptr{Cvoid}, Ptr{Cvoid}),
threadid, heartbeat_c, sock)
threadid, heartbeat_c, heartbeat)
end
6 changes: 4 additions & 2 deletions src/init.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const raw_input = Ref{Socket}()
const requests = Ref{Socket}()
const control = Ref{Socket}()
const heartbeat = Ref{Socket}()
const heartbeat_context = Ref{Context}()
const profile = Dict{String,Any}()
const read_stdout = Ref{Base.PipeEndpoint}()
const read_stderr = Ref{Base.PipeEndpoint}()
Expand Down Expand Up @@ -87,7 +88,8 @@ function init(args)
raw_input[] = Socket(ROUTER)
requests[] = Socket(ROUTER)
control[] = Socket(ROUTER)
heartbeat[] = Socket(ROUTER)
heartbeat_context[] = Context()
heartbeat = Socket(heartbeat_context[], ROUTER)
sep = profile["transport"]=="ipc" ? "-" : ":"
bind(publish[], "$(profile["transport"])://$(profile["ip"])$(sep)$(profile["iopub_port"])")
bind(requests[], "$(profile["transport"])://$(profile["ip"])$(sep)$(profile["shell_port"])")
Expand All @@ -97,7 +99,7 @@ function init(args)

# associate a lock with each socket so that multi-part messages
# on a given socket don't get inter-mingled between tasks.
for s in (publish[], raw_input[], requests[], control[], heartbeat[])
for s in (publish[], raw_input[], requests[], control[])
socket_locks[s] = ReentrantLock()
end

Expand Down
6 changes: 5 additions & 1 deletion test/install.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ import IJulia, JSON
end
end

let kspec = IJulia.installkernel("ahzAHZ019.-_ ~!@#%^&*()")
let kspec = IJulia.installkernel("ahzAHZ019.-_ ~!@#%^&*()"; displayname="foo")
try
@test occursin("ahzahz019.-_-__________", basename(kspec))

let k = open(JSON.parse, joinpath(kspec, "kernel.json"))
@test k["display_name"] == "foo"
end
finally
rm(kspec, force=true, recursive=true)
end
Expand Down

0 comments on commit 57df15d

Please sign in to comment.