Skip to content

Commit

Permalink
process: implement getpid (#30013)
Browse files Browse the repository at this point in the history
Closes #4752
  • Loading branch information
vtjnash committed Nov 18, 2018
1 parent 6b2d211 commit b87ab60
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 7 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ New library functions

* `splitpath(p::String)` function, which is the opposite of `joinpath(parts...)`: it splits a filepath into its components ([#28156]).
* `isnothing(::Any)` function, to check whether something is a `Nothing`, returns a `Bool` ([#29679]).
* `getpid(::Process)` method ([#24064]).


Standard library changes
------------------------
Expand Down
19 changes: 17 additions & 2 deletions base/process.jl
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ function uv_return_spawn(p::Ptr{Cvoid}, exit_status::Int64, termsignal::Int32)
proc.exitcode = exit_status
proc.termsignal = termsignal
ccall(:jl_close_uv, Cvoid, (Ptr{Cvoid},), proc.handle)
proc.handle = C_NULL
notify(proc.exitnotify)
nothing
end
Expand Down Expand Up @@ -682,7 +683,7 @@ function test_success(proc::Process)
#TODO: this codepath is not currently tested
throw(_UVError("could not start process $(string(proc.cmd))", proc.exitcode))
end
proc.exitcode == 0 && (proc.termsignal == 0 || proc.termsignal == SIGPIPE)
return proc.exitcode == 0 && (proc.termsignal == 0 || proc.termsignal == SIGPIPE)
end

function success(x::Process)
Expand Down Expand Up @@ -744,6 +745,20 @@ kill(ps::Vector{Process}) = foreach(kill, ps)
kill(ps::ProcessChain) = foreach(kill, ps.processes)
kill(p::Process) = kill(p, SIGTERM)

"""
getpid(process) -> Int32
Get the child process ID, if it still exists.
"""
function Libc.getpid(p::Process)
ppid = Int32(0)
if p.handle != C_NULL
ppid = ccall(:jl_uv_process_pid, Int32, (Ptr{Cvoid},), p.handle)
end
ppid <= 0 && throw(_UVError("getpid", UV_ESRCH))
return ppid
end

function _contains_newline(bufptr::Ptr{Cvoid}, len::Int32)
return (ccall(:memchr, Ptr{Cvoid}, (Ptr{Cvoid},Int32,Csize_t), bufptr, '\n', len) != C_NULL)
end
Expand All @@ -755,7 +770,7 @@ end
Determine whether a process is currently running.
"""
process_running(s::Process) = s.exitcode == typemin(fieldtype(Process, :exitcode))
process_running(s::Process) = s.handle != C_NULL
process_running(s::Vector{Process}) = any(process_running, s)
process_running(s::ProcessChain) = process_running(s.processes)

Expand Down
7 changes: 4 additions & 3 deletions src/jl_uv.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ void jl_uv_flush(uv_stream_t *stream)
return;
while (uv_is_writable(stream) && stream->write_queue_size != 0) {
int fired = 0;
uv_buf_t buf;
buf.base = (char*)(&buf + 1);
buf.len = 0;
uv_buf_t buf;
buf.base = (char*)(&buf + 1);
buf.len = 0;
uv_write_t *write_req = (uv_write_t*)malloc(sizeof(uv_write_t));
write_req->data = (void*)&fired;
if (uv_write(write_req, stream, &buf, 1, uv_flush_callback) != 0)
Expand All @@ -165,6 +165,7 @@ void jl_uv_flush(uv_stream_t *stream)
}

// getters and setters
JL_DLLEXPORT int jl_uv_process_pid(uv_process_t *p) { return p->pid; }
JL_DLLEXPORT void *jl_uv_process_data(uv_process_t *p) { return p->data; }
JL_DLLEXPORT void *jl_uv_buf_base(const uv_buf_t *buf) { return buf->base; }
JL_DLLEXPORT size_t jl_uv_buf_len(const uv_buf_t *buf) { return buf->len; }
Expand Down
8 changes: 6 additions & 2 deletions test/spawn.jl
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,14 @@ if valgrind_off
end

# setup_stdio for AbstractPipe
let out = Pipe(), proc = run(pipeline(`$echocmd "Hello World"`, stdout=IOContext(out,stdout)), wait=false)
let out = Pipe(),
proc = run(pipeline(`$exename --startup-file=no -e 'println(getpid())'`, stdout=IOContext(out, :foo => :bar)), wait=false)
# < don't block here before getpid call >
pid = getpid(proc)
close(out.in)
@test read(out, String) == "Hello World\n"
@test parse(Int32, read(out, String)) === pid > 1
@test success(proc)
@test_throws Base.IOError getpid(proc)
end

# issue #5904
Expand Down

0 comments on commit b87ab60

Please sign in to comment.