Skip to content

Commit 1b68365

Browse files
phymbertcebtenzzre
authored andcommitted
server: ci: windows build and tests (ggml-org#5968)
* server: ci: windows build and tests * server: ci: remove tmp push branch * server: ci: EOF EOL * Use builti Co-authored-by: Jared Van Bortel <[email protected]> * server: tests: server graceful shutdown, then kill, then hard kill * server: tests: remove python2 unicode string * server: tests: remove wrong comment on server starting, close_fds is always true * server: tests: server kill, if pid exists * server: tests: remove dependency to killall * server: tests: ci windows: pid exists better handling --------- Co-authored-by: Jared Van Bortel <[email protected]>
1 parent 548345e commit 1b68365

File tree

4 files changed

+191
-99
lines changed

4 files changed

+191
-99
lines changed

.github/workflows/server.yml

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ jobs:
4747
- name: Clone
4848
id: checkout
4949
uses: actions/checkout@v3
50+
with:
51+
fetch-depth: 0
5052

5153
- name: Dependencies
5254
id: depends
@@ -58,7 +60,6 @@ jobs:
5860
cmake \
5961
python3-pip \
6062
wget \
61-
psmisc \
6263
language-pack-en
6364
6465
- name: Build
@@ -90,3 +91,46 @@ jobs:
9091
run: |
9192
cd examples/server/tests
9293
PORT=8888 ./tests.sh --stop --no-skipped --no-capture --tags slow
94+
95+
96+
server-windows:
97+
runs-on: windows-latest
98+
99+
steps:
100+
- name: Clone
101+
id: checkout
102+
uses: actions/checkout@v3
103+
with:
104+
fetch-depth: 0
105+
106+
- name: Build
107+
id: cmake_build
108+
run: |
109+
mkdir build
110+
cd build
111+
cmake .. -DLLAMA_BUILD_SERVER=ON -DCMAKE_BUILD_TYPE=Release ;
112+
cmake --build . --config Release -j ${env:NUMBER_OF_PROCESSORS} --target server
113+
114+
- name: Python setup
115+
id: setup_python
116+
uses: actions/setup-python@v5
117+
with:
118+
python-version: '3.11'
119+
120+
- name: Tests dependencies
121+
id: test_dependencies
122+
run: |
123+
pip install -r examples/server/tests/requirements.txt
124+
125+
- name: Tests
126+
id: server_integration_tests
127+
run: |
128+
cd examples/server/tests
129+
behave.exe --summary --stop --no-capture --exclude 'issues|wrong_usages|passkey' --tags llama.cpp
130+
131+
- name: Slow tests
132+
id: server_integration_tests_slow
133+
if: ${{ github.event.schedule != '' || github.event.inputs.slow_tests == 'true' }}
134+
run: |
135+
cd examples/server/tests
136+
behave.exe --stop --no-skipped --no-capture --tags slow
Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import errno
12
import os
23
import socket
34
import subprocess
45
import time
56
from contextlib import closing
6-
from signal import SIGKILL
7+
import signal
78

89

910
def before_scenario(context, scenario):
@@ -29,44 +30,71 @@ def after_scenario(context, scenario):
2930
for line in f:
3031
print(line)
3132
if not is_server_listening(context.server_fqdn, context.server_port):
32-
print("\x1b[33;101mERROR: Server stopped listening\x1b[0m")
33+
print("\x1b[33;101mERROR: Server stopped listening\x1b[0m\n")
3334

3435
if not pid_exists(context.server_process.pid):
3536
assert False, f"Server not running pid={context.server_process.pid} ..."
3637

37-
print(f"stopping server pid={context.server_process.pid} ...")
38-
context.server_process.kill()
38+
server_graceful_shutdown(context)
39+
3940
# Wait few for socket to free up
4041
time.sleep(0.05)
4142

4243
attempts = 0
43-
while is_server_listening(context.server_fqdn, context.server_port):
44-
print(f"stopping server pid={context.server_process.pid} ...")
45-
os.kill(context.server_process.pid, SIGKILL)
44+
while pid_exists(context.server_process.pid) or is_server_listening(context.server_fqdn, context.server_port):
45+
server_kill(context)
4646
time.sleep(0.1)
4747
attempts += 1
4848
if attempts > 5:
49-
print(f"Server dangling exits, killing all {context.server_path} ...")
50-
process = subprocess.run(['killall', '-9', context.server_path],
51-
stderr=subprocess.PIPE,
52-
universal_newlines=True)
53-
print(process)
49+
server_kill_hard(context)
50+
51+
52+
def server_graceful_shutdown(context):
53+
print(f"shutting down server pid={context.server_process.pid} ...\n")
54+
if os.name == 'nt':
55+
os.kill(context.server_process.pid, signal.CTRL_C_EVENT)
56+
else:
57+
os.kill(context.server_process.pid, signal.SIGINT)
58+
59+
60+
def server_kill(context):
61+
print(f"killing server pid={context.server_process.pid} ...\n")
62+
context.server_process.kill()
63+
64+
65+
def server_kill_hard(context):
66+
pid = context.server_process.pid
67+
path = context.server_path
68+
69+
print(f"Server dangling exits, hard killing force {pid}={path}...\n")
70+
if os.name == 'nt':
71+
process = subprocess.check_output(['taskkill', '/F', '/pid', str(pid)]).decode()
72+
print(process)
73+
else:
74+
os.kill(-pid, signal.SIGKILL)
5475

5576

5677
def is_server_listening(server_fqdn, server_port):
5778
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
5879
result = sock.connect_ex((server_fqdn, server_port))
59-
return result == 0
80+
_is_server_listening = result == 0
81+
if _is_server_listening:
82+
print(f"server is listening on {server_fqdn}:{server_port}...\n")
83+
return _is_server_listening
6084

6185

6286
def pid_exists(pid):
6387
"""Check whether pid exists in the current process table."""
64-
import errno
6588
if pid < 0:
6689
return False
67-
try:
68-
os.kill(pid, 0)
69-
except OSError as e:
70-
return e.errno == errno.EPERM
90+
if os.name == 'nt':
91+
output = subprocess.check_output(['TASKLIST', '/FI', f'pid eq {pid}']).decode()
92+
print(output)
93+
return "No tasks are running" not in output
7194
else:
72-
return True
95+
try:
96+
os.kill(pid, 0)
97+
except OSError as e:
98+
return e.errno == errno.EPERM
99+
else:
100+
return True

examples/server/tests/features/server.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Feature: llama.cpp server
4747
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
4848
"""
4949
And a completion request with no api error
50-
Then 64 tokens are predicted matching fun|Annaks|popcorns
50+
Then 64 tokens are predicted matching fun|Annaks|popcorns|pictry
5151
And the completion is truncated
5252
And 109 prompt tokens are processed
5353

0 commit comments

Comments
 (0)