Skip to content

Instantly share code, notes, and snippets.

@JanWielemaker
Created November 14, 2019 13:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JanWielemaker/d9837fb1858d76d5dfd9caa3851db057 to your computer and use it in GitHub Desktop.
Save JanWielemaker/d9837fb1858d76d5dfd9caa3851db057 to your computer and use it in GitHub Desktop.
:- module(fork_client,
[ fork_client/2,
stop_client/1,
run_in_client/2
]).
:- use_module(library(socket)).
fork_client(Address, Stream) :-
tcp_connect(Address, Stream, []).
stop_client(Stream) :-
reply(Stream, quit),
close(Stream).
run_in_client(Stream, Goal) :-
term_variables(Goal, Vars),
reply(Stream, run(Goal, Vars)),
read(Stream, Reply),
( Reply = true(Vars0)
-> Vars0 = Vars
; Reply = exception(E)
-> throw(E)
).
reply(Stream, Term) :-
write_term(Stream, Term,
[ quoted(true),
ignore_ops(true),
fullstop(true)
]),
flush_output(Stream).
:- module(fork_server,
[ fork_server/1
]).
:- use_module(library(socket)).
fork_server(Port) :-
tcp_socket(Socket),
tcp_setopt(Socket, reuseaddr),
tcp_bind(Socket, Port),
tcp_listen(Socket, 5),
tcp_open_socket(Socket, AcceptFd, _),
dispatch(AcceptFd).
dispatch(AcceptFd) :-
tcp_accept(AcceptFd, Socket, Peer),
fork(Pid),
( Pid == child
-> serve(Socket, Peer)
; tcp_close_socket(Socket),
dispatch(AcceptFd)
).
serve(Socket, _Peer) :-
tcp_open_socket(Socket, Read, Write),
serve_loop(Read, Write).
serve_loop(Read, Write) :-
read(Read, Command),
( Command == quit
-> reply(Write, bye)
; Command = run(Goal, Vars)
-> ( catch(Goal, E, true)
-> ( var(E)
-> reply(Write, true(Vars))
; reply(Write, exception(E))
)
; reply(Write, false)
),
serve_loop(Read, Write)
).
reply(Stream, Term) :-
write_term(Stream, Term,
[ quoted(true),
ignore_ops(true),
fullstop(true)
]),
flush_output(Stream).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment