go-judge

中文文档 | Documentation
Fast, Simple, Secure
Quick Start
Install & Run
Download compiled executable go-judge
for your platform from Release and run.
Or, by docker
docker run -it --rm --privileged --shm-size=256m -p 5050:5050 --name=go-judge criyle/go-judge
REST API
A REST service to run program in restricted environment (Listening on localhost:5050
by default).
- POST /run execute program in the restricted environment
- GET /file list all cached file id to original name map
- POST /file prepare a file in the go judge (in memory), returns fileId (can be referenced in /run parameter)
- GET /file/:fileId downloads file from go judge (in memory), returns file content
- DELETE /file/:fileId delete file specified by fileId
- /ws WebSocket version for /run
- /stream WebSocket for stream run. Supports streaming interface
- GET /version gets build git version (e.g.
v1.9.0
) together with runtime information (go version, os, platform)
- GET /config gets some configuration (e.g.
fileStorePath
, runnerConfig
) together with some supported features
REST API Interface
API Interface Structure Definition
Example Request & Response
Example Request & Response
Documentation
Prerequisite
- Linux Kernel Version >= 3.10
- Cgroup file system mounted at /sys/fs/cgroup. Usually done by systemd
Architecture
+----------------------------------------------------------------------------------+
| Transport Layer (HTTP / WebSocket / FFI / ...) |
+----------------------------------------------------------------------------------+
| Sandbox Worker (Environment Pool w/ Environment Builder ) |
+-----------------------------------------------------------+----------------------+
| EnvExec | File Store |
+--------------------+----------------+---------------------+---------------+------+
| Linux (go-sandbox) | Windows (winc) | macOS (app sandbox) | Shared Memory | Disk |
+--------------------+----------------+---------------------+---------------+------+
Configurations
Server:
- The default binding address for the go judge is
localhost:5050
. Can be specified with -http-addr
flag.
- By default gRPC endpoint is disabled, to enable gRPC endpoint, add
-enable-grpc
flag.
- The default binding address for the gRPC go judge is
localhost:5051
. Can be specified with -grpc-addr
flag.
- The default log level is info, use
-silent
to disable logs or use -release
to enable release logger (auto turn on if in docker).
-auth-token
to add token-based authentication to REST / gRPC
- By default, the GO debug endpoints (
localhost:5052/debug
) are disabled, to enable, specifies -enable-debug
, and it also enables debug log
- By default, the prometheus metrics endpoints (
localhost:5052/metrics
) are disabled, to enable, specifies -enable-metrics
- Monitoring HTTP endpoint is enabled if metrics / debug is enabled, the default addr is
localhost:5052
and can be specified by -monitor-addr
Sandbox:
- The default concurrency equal to number of CPU, Can be specified with
-parallelism
flag.
-mount-conf
specifies detailed mount configuration, please refer File System Mount as a reference (Linux only)
-file-timeout
specifies maximum TTL for file created in file store (e.g. 30m
)
- The default file store is in memory(
/dev/shm/
), local cache can be specified with -dir
flag.
-output-limit
specifies size limit of POSIX rlimit of output (default 256MiB)
-copy-out-limit
specifies the default file copy out max (default 64MiB)
You can find more available configuration here.
Run Terminal in the Container
Download go-judge-shell
from Release and run. It will connect local go-judge
, and open an interactive shell in the container for debugging purpose.
Return Status
- Accepted: Program exited with status code 0 within time & memory limits
- Memory Limit Exceeded: Program uses more memory than memory limits
- Time Limit Exceeded: (
exitStatus
usually have value 9
as killed by SIGKILL
after timeout)
- Program uses more CPU time than cpuLimit
- Or, program uses more clock time than clockLimit
- Output Limit Exceeded:
- Program output more than pipeCollector limits
- Or, program output more than output-limit
- File Error:
- CopyIn file is not existed
- Or, CopyIn file too large for container file system
- Or, CopyOut file is not existed after program exited
- Non Zero Exit Status: Program exited with non 0 status code within time & memory limits
- Signalled: Program exited with signal (e.g.
SIGSEGV
)
- Dangerous Syscall: Program killed by seccomp filter (not enabled by default)
- Internal Error:
- Program is not exist
- Or, container create not successful (e.g. not privileged docker)
- Or, other errors
Container Root Filesystem
For linux platform, the default mounts points are bind mounting host's /lib
, /lib64
, /usr
, /bin
, /etc/ld.so.cache
, /etc/alternatives
, /etc/fpc.cfg
, /dev/null
, /dev/urandom
, /dev/random
, /dev/zero
, /dev/full
and mounts tmpfs at /w
, /tmp
and creates /proc
.
To customize mount points, please look at example mount.yaml
file.
If mount.yaml
is not specified, the size of tmpfs
for /w
and /tmp
is configured through -tmp-fs-param
with default value size=128m,nr_inodes=4k
If a file named /.env
exists in the container rootfs, the container will load the file as environment variable line by line.
If a bind mount is specifying a target within the previous mounted one, please ensure the target exists in the previous mount point.
Metrics Monitoring Endpoint
Prometheus Metrics Monitoring Endpoint
Notice
[!WARNING]
Window and macOS support are experimental and should not be used in production environments
cgroup usage
For cgroup v1, the go-judge
need root privilege to create cgroup
. Either creates sub-directory /sys/fs/cgroup/cpuacct/gojudge
, /sys/fs/cgroup/memory/gojudge
, /sys/fs/cgroup/pids/gojudge
and make execution user readable or use sudo
to run it.
For cgroup v2, systemd dbus will be used to create a transient scope for cgroup integration.
If no permission to create cgroup, the cgroup related limit will not be effective.
cgroup v2 support
The cgroup v2 is supported by go-judge
now when running as root since more Linux distribution are enabling cgroup v2 by default (e.g. Ubuntu 21.10+, Fedora 31+). However, for kernel < 5.19, due to missing memory.max_usage_in_bytes
in memory
controller, the memory usage is now accounted by maxrss
returned by wait4
syscall. Thus, the memory usage appears higher than those who uses cgroup v1. For kernel >= 5.19, memory.peak
is being used.
When running in containers, the go-judge
will migrate all processed into /api
hierarchy to enable nesting support.
When running in Linux distributions powered by systemd
, the go-judge
will contact systemd
via dbus
to create a transient scope as cgroup root.
When running with kernel >= 5.7, the go-judge
will try faster clone3(CLONE_INTO_CGROUP)
and vfork
method.
Memory Usage
The controller usually consumes 20M
memory and each container usually consumes 20M
+ size of tmpfs 2 * 128M
. For each request, it consumes as much as user program limit + extra limit (16k
) + total copy out max. Notice that the cached file stores in the shared memory (/dev/shm
) of the host, so please ensure enough size allocated.
For example, when concurrency = 4, the container itself can consume as much as 60 + (20+32) * 4M = 268M
+ 4 * total copy out + total max memory of requests.
Due to limitation of GO runtime, the memory will not return to OS automatically, which could lead to OOM killer. A background worker was introduced to checks heap usage and invokes GC when necessary.
-force-gc-target
default 20m
, the minimal size to trigger GC
-force-gc-interval
default 5s
, the interval to check memory usage