Skip to content

Commit 57df15d

Browse files
Merge branch 'master' into messaging-updates
2 parents f63ccfb + 2164bfc commit 57df15d

File tree

8 files changed

+45
-16
lines changed

8 files changed

+45
-16
lines changed

.github/workflows/CI.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,18 @@ jobs:
2121
- os: ubuntu-latest
2222
julia-arch: x86
2323
julia-version: '1'
24+
2425
steps:
2526
- uses: actions/checkout@v4
2627
- uses: julia-actions/setup-julia@v2
2728
with:
2829
version: ${{ matrix.julia-version }}
2930
arch: ${{ matrix.julia-arch }}
30-
- uses: julia-actions/cache@v1
31+
- uses: julia-actions/cache@v2
3132
- uses: julia-actions/julia-buildpkg@v1
3233
- uses: julia-actions/julia-runtest@v1
34+
- uses: julia-actions/julia-processcoverage@v1
35+
- uses: codecov/codecov-action@v5
36+
with:
37+
files: lcov.info
38+
token: ${{ secrets.CODECOV_TOKEN }}

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ Conda = "1"
2626
JSON = "0.18,0.19,0.20,0.21,1"
2727
MbedTLS = "0.5,0.6,0.7,1"
2828
SoftGlobalScope = "1"
29-
ZMQ = "1"
29+
ZMQ = "1.3"
3030
julia = "1.10"

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ If you already have Python/Jupyter installed on your machine, this process will
3636
that tells Jupyter how to launch Julia. You can then launch the notebook server the usual
3737
way by running `jupyter notebook` in the terminal.
3838

39+
Note that `IJulia` should generally be installed in Julia's global package environment, unless you
40+
install a custom kernel that specifies a particular environment.
41+
3942
Alternatively, you can have IJulia create and manage its own Python/Jupyter installation.
4043
To do this, type the following in Julia, at the `julia>` prompt:
4144

deps/kspec.jl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,16 @@ else
5454
exe(s::AbstractString, e::AbstractString) = s * e
5555
end
5656

57+
function display_name(name::AbstractString)
58+
debugdesc = ccall(:jl_is_debugbuild,Cint,())==1 ? "-debug" : ""
59+
return name * " " * Base.VERSION_STRING * debugdesc
60+
end
61+
5762
"""
5863
installkernel(name::AbstractString, options::AbstractString...;
5964
julia::Cmd,
6065
specname::AbstractString,
66+
displayname::AbstractString,
6167
env=Dict())
6268
6369
Install a new Julia kernel, where the given `options` are passed to the `julia`
@@ -71,6 +77,9 @@ kernelpath = installkernel("Julia O3", "-O3", env=Dict("FOO"=>"yes"))
7177
creates a new Julia kernel in which `julia` is launched with the `-O3`
7278
optimization flag and `FOO=yes` is included in the environment variables.
7379
80+
The `displayname` argument can be used to customize the name displayed in the
81+
Jupyter kernel list.
82+
7483
The returned `kernelpath` is the path of the installed kernel directory,
7584
something like `/...somepath.../kernels/julia-o3-1.6` (in Julia 1.6). The
7685
`specname` argument can be passed to alter the name of this directory (which
@@ -96,6 +105,7 @@ installkernel(
96105
function installkernel(name::AbstractString, julia_options::AbstractString...;
97106
julia::Cmd = `$(joinpath(Sys.BINDIR,exe("julia")))`,
98107
specname::AbstractString = kernelspec_name(name),
108+
displayname::AbstractString = display_name(name),
99109
env::Dict{<:AbstractString}=Dict{String,Any}())
100110
# Is IJulia being built from a debug build? If so, add "debug" to the description.
101111
debugdesc = ccall(:jl_is_debugbuild,Cint,())==1 ? "-debug" : ""
@@ -112,7 +122,7 @@ function installkernel(name::AbstractString, julia_options::AbstractString...;
112122

113123
ks = Dict(
114124
"argv" => kernelcmd_array,
115-
"display_name" => name * " " * Base.VERSION_STRING * debugdesc,
125+
"display_name" => displayname,
116126
"language" => "julia",
117127
"env" => env,
118128
# Jupyter's signal interrupt mode is not supported on Windows

src/handlers.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,10 @@ function connect_request(socket, msg)
189189
end
190190

191191
function shutdown_request(socket, msg)
192-
send_ipython(socket, msg_reply(msg, "shutdown_reply",
192+
# stop heartbeat thread by closing the context
193+
close(heartbeat_context[])
194+
195+
send_ipython(requests[], msg_reply(msg, "shutdown_reply",
193196
msg.content))
194197
sleep(0.1) # short delay (like in ipykernel), to hopefully ensure shutdown_reply is sent
195198
exit()

src/heartbeat.jl

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77
import Libdl
88

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

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

27-
function start_heartbeat(sock)
28-
zmq_proxy[] = Libdl.dlsym(Libdl.dlopen(ZMQ.libzmq), :zmq_proxy)
29-
heartbeat_c = @cfunction(heartbeat_thread, Cvoid, (Ptr{Cvoid},))
29+
function start_heartbeat(heartbeat)
30+
heartbeat_c = @cfunction(heartbeat_thread, Cint, (Ptr{Cvoid},))
3031
ccall(:uv_thread_create, Cint, (Ptr{Int}, Ptr{Cvoid}, Ptr{Cvoid}),
31-
threadid, heartbeat_c, sock)
32+
threadid, heartbeat_c, heartbeat)
3233
end

src/init.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const raw_input = Ref{Socket}()
2525
const requests = Ref{Socket}()
2626
const control = Ref{Socket}()
2727
const heartbeat = Ref{Socket}()
28+
const heartbeat_context = Ref{Context}()
2829
const profile = Dict{String,Any}()
2930
const read_stdout = Ref{Base.PipeEndpoint}()
3031
const read_stderr = Ref{Base.PipeEndpoint}()
@@ -87,7 +88,8 @@ function init(args)
8788
raw_input[] = Socket(ROUTER)
8889
requests[] = Socket(ROUTER)
8990
control[] = Socket(ROUTER)
90-
heartbeat[] = Socket(ROUTER)
91+
heartbeat_context[] = Context()
92+
heartbeat = Socket(heartbeat_context[], ROUTER)
9193
sep = profile["transport"]=="ipc" ? "-" : ":"
9294
bind(publish[], "$(profile["transport"])://$(profile["ip"])$(sep)$(profile["iopub_port"])")
9395
bind(requests[], "$(profile["transport"])://$(profile["ip"])$(sep)$(profile["shell_port"])")
@@ -97,7 +99,7 @@ function init(args)
9799

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

test/install.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@ import IJulia, JSON
2222
end
2323
end
2424

25-
let kspec = IJulia.installkernel("ahzAHZ019.-_ ~!@#%^&*()")
25+
let kspec = IJulia.installkernel("ahzAHZ019.-_ ~!@#%^&*()"; displayname="foo")
2626
try
2727
@test occursin("ahzahz019.-_-__________", basename(kspec))
28+
29+
let k = open(JSON.parse, joinpath(kspec, "kernel.json"))
30+
@test k["display_name"] == "foo"
31+
end
2832
finally
2933
rm(kspec, force=true, recursive=true)
3034
end

0 commit comments

Comments
 (0)