44import threading
55import logging
66import argparse
7- import check_requirements
87from utils .logger_utils import setup_logger
98import datetime
109import multiprocessing
1110from server import main
1211import random
12+ import select
13+
1314
1415# Set up logging
1516log_dir = None
1617start_team_logger = None
1718
1819def run_server_script (args ):
20+ rpc_port = args .rpc_port
21+ if args .use_random_port or args .use_different_port :
22+ import socket
23+ with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as s :
24+ s .bind (('localhost' , 0 ))
25+ rpc_port = str (s .getsockname ()[1 ])
26+ start_team_logger .debug (f"Using random port: { rpc_port } " )
1927 # Define a wrapper function to pass the arguments to the main function
2028 def server_main ():
2129 import sys
22- sys .argv = ['server.py' , '--rpc-port' , str (args . rpc_port ), '--log-dir' , log_dir ]
30+ sys .argv = ['server.py' , '--rpc-port' , str (rpc_port ), '--log-dir' , log_dir ]
2331 if args .disable_log_file :
2432 sys .argv += ['--disable-log-file' ]
2533 main ()
2634
2735 # Start the main function as a new process
2836 process = multiprocessing .Process (target = server_main )
2937 process .start ()
30- return process
38+ return process , rpc_port
3139
32- def run_start_script (args ):
40+ def run_start_script (args , rpc_port ):
3341 # Start the start.sh script in its own directory as a new process group
3442 arguments = ['bash' ]
3543 if args .player or args .coach or args .goalie :
@@ -38,7 +46,7 @@ def run_start_script(args):
3846 arguments += ['start.sh' if not args .debug else 'start-debug.sh' ]
3947
4048 arguments += ['-t' , args .team_name ,
41- '--rpc-port' , args . rpc_port , '--rpc-type' , 'grpc' ,
49+ '--rpc-port' , rpc_port , '--rpc-type' , 'grpc' ,
4250 '-p' , args .server_port , '-h' , args .server_host ]
4351
4452 process = subprocess .Popen (
@@ -56,32 +64,39 @@ def stream_output_to_file(process, name, args):
5664 # Stream output from the process and log it to a file with the given name
5765 f = None if args .disable_log_file else open (f"{ log_dir } /{ name } .log" , "a" )
5866 while not stop_thread .is_set ():
59- output = process .stdout .readline ()
60- if output :
61- if f :
62- f .write (output .decode ())
63- f .flush ()
67+ if select .select ([process .stdout ], [], [], 1 )[0 ]:
68+ output = process .stdout .readline ()
69+ if output :
70+ if f :
71+ f .write (output .decode ())
72+ f .flush ()
73+ else :
74+ print (output .decode ())
6475 else :
65- print (output .decode ())
66- else :
67- break
76+ break
6877 process .stdout .close ()
78+ if f :
79+ f .close ()
6980
70- def kill_process_group (process ):
71- try :
72- start_team_logger .debug (f"Killing process group with PID: { process .pid } " )
73- os .killpg (os .getpgid (process .pid ), signal .SIGTERM ) # Send SIGTERM to the process group
74- except ProcessLookupError :
75- pass # The process might have already exited
81+ def kill_process_group (processes ):
82+ for process in processes :
83+ try :
84+ start_team_logger .debug (f"Killing process group with PID: { process .pid } " )
85+ os .killpg (os .getpgid (process .pid ), signal .SIGTERM ) # Send SIGTERM to the process group
86+ except ProcessLookupError :
87+ pass # The process might have already exited
7688
77- def kill_rpc_server_process (process ):
78- try :
79- start_team_logger .debug (f"Killing process with PID: { process .pid } " )
80- os .kill (process .pid , signal .SIGTERM ) # Send SIGTERM to the specific process
81- except ProcessLookupError :
82- pass # The process might have already exited
89+ def kill_rpc_server_process (processes ):
90+ for process in processes :
91+ try :
92+ start_team_logger .debug (f"Killing process with PID: { process .pid } " )
93+ os .kill (process .pid , signal .SIGTERM ) # Send SIGTERM to the specific process
94+ except ProcessLookupError :
95+ pass # The process might have already exited
96+
97+ def check_args (args ):
98+ pass
8399
84-
85100if __name__ == "__main__" :
86101 # Set up argument parsing
87102 parser = argparse .ArgumentParser (description = 'Run server and team scripts.' )
@@ -90,6 +105,7 @@ def kill_rpc_server_process(process):
90105 parser .add_argument ('-d' , '--debug' , required = False , help = 'Enable debug mode' , default = False , action = 'store_true' )
91106 parser .add_argument ('--use-random-port' , required = False , help = 'Use a random port for the server' , default = False , action = 'store_true' )
92107 parser .add_argument ('--use-random-name' , required = False , help = 'Use a random team name' , default = False , action = 'store_true' )
108+ parser .add_argument ('--use-different-port' , required = False , help = 'Use a different port for the rpc server' , default = False , action = 'store_true' )
93109 parser .add_argument ('--server-host' , required = False , help = 'The host of the server' , default = 'localhost' )
94110 parser .add_argument ('--server-port' , required = False , help = 'The port of the server' , default = '6000' )
95111 parser .add_argument ('--close-server' , required = False , help = 'Close the server' , default = False , action = 'store_true' )
@@ -110,47 +126,70 @@ def kill_rpc_server_process(process):
110126 start_team_logger .debug (f"Arguments: { args = } " )
111127
112128 try :
113- if args .use_random_port :
114- import socket
115- with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as s :
116- s .bind (('localhost' , 0 ))
117- args .rpc_port = str (s .getsockname ()[1 ])
118- start_team_logger .debug (f"Using random port: { args .rpc_port } " )
119-
120129 if args .use_random_name :
121130 import random
122131 import string
123132 args .team_name = '' .join (random .choices (string .ascii_uppercase + string .digits , k = 5 ))
124133
125134 # Run the server.py script first
126- server_process = run_server_script (args )
127- start_team_logger .debug (f"Started server.py process with PID: { server_process .pid } " )
128-
129- # Run the start.sh script after server.py with the given arguments
130- start_process = run_start_script (args )
131- start_team_logger .debug (f"Started start.sh process with PID: { start_process .pid } with team name { args = } " )
135+ all_server_processes = []
136+ all_start_processes = []
137+ if args .use_different_port :
138+ for i in range (13 ):
139+ server_process , rpc_port = run_server_script (args )
140+ all_server_processes .append (server_process )
141+ start_team_logger .debug (f"Started server.py process with PID: { all_server_processes [- 1 ].pid } " )
142+ args .goalie , args .coach , args .player = False , False , False
143+ args .player = False
144+ if i == 0 :
145+ args .goalie = True
146+ elif i == 12 :
147+ args .coach = True
148+ else :
149+ args .player = True
150+
151+ # Run the start.sh script after server.py with the given arguments
152+ all_start_processes .append (run_start_script (args , rpc_port ))
153+ start_team_logger .debug (f"Started start.sh process with PID: { all_start_processes [- 1 ].pid } with team name { args = } and rpc port { rpc_port } " )
154+ else :
155+ server_process , rpc_port = run_server_script (args )
156+ all_server_processes .append (server_process )
157+ start_team_logger .debug (f"Started server.py process with PID: { all_server_processes [- 1 ].pid } " )
158+
159+ # Run the start.sh script after server.py with the given arguments
160+ all_start_processes .append (run_start_script (args , rpc_port ))
161+ start_team_logger .debug (f"Started start.sh process with PID: { all_start_processes [- 1 ].pid } with team name { args = } and rpc port { rpc_port } " )
132162
133163 # Monitor both processes and log their outputs
134164 start_team_logger .debug ("Monitoring processes..." )
135165
136- start_thread = threading .Thread (target = stream_output_to_file , args = (start_process , 'proxy' , args ))
137- start_thread .start ()
166+ start_threads : list [threading .Thread ] = []
167+ for i , start_process in enumerate (all_start_processes ):
168+ start_threads .append (threading .Thread (target = stream_output_to_file , args = (start_process , 'proxy' if len (all_start_processes ) == 1 else f'porxy_{ i } ' , args )))
169+ start_threads [- 1 ].start ()
138170
139171 def signal_handler (sig , frame ):
140172 start_team_logger .info ('Received signal to terminate. Cleaning up...' )
141- kill_rpc_server_process (server_process )
142- server_process .join ()
143-
144- start_team_logger .debug (f"server.py ended with PID: { server_process .pid } " )
173+ kill_rpc_server_process (all_server_processes )
174+ for server_process in all_server_processes :
175+ server_process .join ()
176+ start_team_logger .debug (f"server.py ended with PID: { server_process .pid } " )
177+
178+ start_team_logger .debug ("all_server_processes has finished." )
145179
146- kill_process_group (start_process )
147- start_process .wait ()
180+ kill_process_group (all_start_processes )
181+ for start_process in all_start_processes :
182+ start_process .wait ()
183+ start_team_logger .debug (f"start.sh ended with PID: { start_process .pid } " )
148184
149- start_team_logger .debug (f"start.sh ended with PID: { start_process . pid } " )
185+ start_team_logger .debug ("all_start_processes has finished. " )
150186
151187 stop_thread .set ()
152188
153- start_thread .join ()
189+ start_team_logger .debug ("Waiting for start_thread to finish..." )
190+ for start_thread in start_threads :
191+ start_thread .join ()
192+
154193 start_team_logger .debug ("start_thread has finished." )
155194
156195 start_team_logger .info ('All processes have been killed.' )
@@ -160,26 +199,28 @@ def signal_handler(sig, frame):
160199 signal .signal (signal .SIGINT , signal_handler )
161200
162201 # Wait for both threads to finish
163- start_thread .join ()
202+ for start_thread in start_threads :
203+ start_thread .join ()
164204 start_team_logger .debug ("agents has been exited." )
165205
166206 if args .close_server :
167207 start_team_logger .debug ("Closing rpc server ..." )
168- kill_rpc_server_process (server_process )
208+ kill_rpc_server_process (all_server_processes )
169209 start_team_logger .debug ("rpc Server has been closed." )
170210
171211 # wait for server process to finish
172- server_process .join ()
212+ for server_process in all_server_processes :
213+ server_process .join ()
173214 start_team_logger .debug ("server.py has finished." )
174215
175216 start_team_logger .info ("Both processes have exited." )
176217 except KeyboardInterrupt :
177218 start_team_logger .debug ("Interrupted! Killing all processes." )
178- kill_rpc_server_process (server_process )
179- kill_process_group (start_process )
219+ kill_rpc_server_process (all_server_processes )
220+ kill_process_group (all_start_processes )
180221
181222 finally :
182223 # Ensure all processes are killed on exit
183224 start_team_logger .debug ("Final Cleaning up..." )
184- kill_rpc_server_process (server_process )
185- kill_process_group (start_process )
225+ kill_rpc_server_process (all_server_processes )
226+ kill_process_group (all_start_processes )
0 commit comments