From 922ed8165f3d9f5f23af257d58f36d9a4ba1f0fa Mon Sep 17 00:00:00 2001 From: Benjamin Davis Date: Sat, 30 Oct 2021 02:09:48 -0400 Subject: [PATCH 1/4] Fixes PROS hanging on "pros make" with no toolchain --- pros/conductor/project/__init__.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pros/conductor/project/__init__.py b/pros/conductor/project/__init__.py index bbc191c4..08739ecb 100644 --- a/pros/conductor/project/__init__.py +++ b/pros/conductor/project/__init__.py @@ -224,10 +224,15 @@ def make(self, build_args: List[str]): make_cmd = os.path.join(os.environ.get('PROS_TOOLCHAIN'), 'bin', 'make.exe') else: make_cmd = 'make' - stdout_pipe = EchoPipe() - stderr_pipe = EchoPipe(err=True) - process = subprocess.Popen(executable=make_cmd, args=[make_cmd, *build_args], cwd=self.directory, env=env, + process,stdout_pipe,stderr_pipe=(None,None,None) + try: + process = subprocess.Popen(executable=make_cmd, args=[make_cmd, *build_args], cwd=self.directory, env=env, stdout=stdout_pipe, stderr=stderr_pipe) + stdout_pipe=process.communicate() + stderr_pipe=process.communicate() + except Exception: + print("\nError | PROS Toolchain Not Found! Are you sure you installed PROS correctly?") + sys.exit() stdout_pipe.close() stderr_pipe.close() process.wait() From d068422afa218a883193b57cccc8dc99f7c4a95e Mon Sep 17 00:00:00 2001 From: Benjamin Davis Date: Sat, 30 Oct 2021 18:05:01 -0400 Subject: [PATCH 2/4] Adds new "Subprocess" class. Logs errors and doesn't hang on exit. --- pros/conductor/project/ProjectSubprocess.py | 32 +++++++++++++++++++++ pros/conductor/project/__init__.py | 15 ++-------- 2 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 pros/conductor/project/ProjectSubprocess.py diff --git a/pros/conductor/project/ProjectSubprocess.py b/pros/conductor/project/ProjectSubprocess.py new file mode 100644 index 00000000..14b901c0 --- /dev/null +++ b/pros/conductor/project/ProjectSubprocess.py @@ -0,0 +1,32 @@ +import subprocess +import sys +from pros.common.utils import logger +class Subprocess: + def __init__(self,exe,arg,c,e): + self.ex=exe + self.arg=arg + self.c=c + self.e=e + self.process,self.stdout_pipe,self.stderr_pipe = (None,None,None) + self.start() + + def start(self): + try: + self.process = subprocess.Popen(executable=self.ex,args=self.arg,cwd=self.c,env=self.e, + stdout=subprocess.PIPE,stderr=subprocess.PIPE) + self.stdout_pipe,self.stderr_pipe=self.process.communicate() + self.process.wait() + self.close_pipes() + except Exception as e: + self.error_handle(e) + + def error_handle(self,e): + if type(e)==FileNotFoundError: + logger(__name__).error("\nUnable to locate executable \'" + self.ex + ".exe\'! Are you sure PROS was installed correctly?\n"+str(e)) + else: + logger(__name__).error(e) + sys.exit() + + def close_pipes(self): + self.stdout_pipe.close() + self.stderr_pipe.close() diff --git a/pros/conductor/project/__init__.py b/pros/conductor/project/__init__.py index 08739ecb..2f86f4a9 100644 --- a/pros/conductor/project/__init__.py +++ b/pros/conductor/project/__init__.py @@ -213,7 +213,7 @@ def output(self): return 'bin/output.bin' def make(self, build_args: List[str]): - import subprocess + from .ProjectSubprocess import Subprocess env = os.environ.copy() # Add PROS toolchain to the beginning of PATH to ensure PROS binaries are preferred if os.environ.get('PROS_TOOLCHAIN'): @@ -224,18 +224,7 @@ def make(self, build_args: List[str]): make_cmd = os.path.join(os.environ.get('PROS_TOOLCHAIN'), 'bin', 'make.exe') else: make_cmd = 'make' - process,stdout_pipe,stderr_pipe=(None,None,None) - try: - process = subprocess.Popen(executable=make_cmd, args=[make_cmd, *build_args], cwd=self.directory, env=env, - stdout=stdout_pipe, stderr=stderr_pipe) - stdout_pipe=process.communicate() - stderr_pipe=process.communicate() - except Exception: - print("\nError | PROS Toolchain Not Found! Are you sure you installed PROS correctly?") - sys.exit() - stdout_pipe.close() - stderr_pipe.close() - process.wait() + process = Subprocess(make_cmd,[make_cmd,*build_args],self.directory,env) return process.returncode def make_scan_build(self, build_args: Tuple[str], cdb_file: Optional[Union[str, io.IOBase]] = None, From d5e6660397455633fef1d738ced9cf9b38efd21d Mon Sep 17 00:00:00 2001 From: Benjamin Davis Date: Mon, 1 Nov 2021 23:44:00 -0400 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=90=9BFixes=20CLI=20hanging=20in=20ma?= =?UTF-8?q?ke=20command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pros/conductor/project/ProjectSubprocess.py | 32 --------------------- pros/conductor/project/__init__.py | 30 +++++++++++++++++-- 2 files changed, 27 insertions(+), 35 deletions(-) delete mode 100644 pros/conductor/project/ProjectSubprocess.py diff --git a/pros/conductor/project/ProjectSubprocess.py b/pros/conductor/project/ProjectSubprocess.py deleted file mode 100644 index 14b901c0..00000000 --- a/pros/conductor/project/ProjectSubprocess.py +++ /dev/null @@ -1,32 +0,0 @@ -import subprocess -import sys -from pros.common.utils import logger -class Subprocess: - def __init__(self,exe,arg,c,e): - self.ex=exe - self.arg=arg - self.c=c - self.e=e - self.process,self.stdout_pipe,self.stderr_pipe = (None,None,None) - self.start() - - def start(self): - try: - self.process = subprocess.Popen(executable=self.ex,args=self.arg,cwd=self.c,env=self.e, - stdout=subprocess.PIPE,stderr=subprocess.PIPE) - self.stdout_pipe,self.stderr_pipe=self.process.communicate() - self.process.wait() - self.close_pipes() - except Exception as e: - self.error_handle(e) - - def error_handle(self,e): - if type(e)==FileNotFoundError: - logger(__name__).error("\nUnable to locate executable \'" + self.ex + ".exe\'! Are you sure PROS was installed correctly?\n"+str(e)) - else: - logger(__name__).error(e) - sys.exit() - - def close_pipes(self): - self.stdout_pipe.close() - self.stderr_pipe.close() diff --git a/pros/conductor/project/__init__.py b/pros/conductor/project/__init__.py index 2f86f4a9..be73c95a 100644 --- a/pros/conductor/project/__init__.py +++ b/pros/conductor/project/__init__.py @@ -213,7 +213,7 @@ def output(self): return 'bin/output.bin' def make(self, build_args: List[str]): - from .ProjectSubprocess import Subprocess + import subprocess env = os.environ.copy() # Add PROS toolchain to the beginning of PATH to ensure PROS binaries are preferred if os.environ.get('PROS_TOOLCHAIN'): @@ -224,7 +224,22 @@ def make(self, build_args: List[str]): make_cmd = os.path.join(os.environ.get('PROS_TOOLCHAIN'), 'bin', 'make.exe') else: make_cmd = 'make' - process = Subprocess(make_cmd,[make_cmd,*build_args],self.directory,env) + stdout_pipe = EchoPipe() + stderr_pipe = EchoPipe(err=True) + process=None + try: + process = subprocess.Popen(executable=make_cmd, args=[make_cmd, *build_args], cwd=self.directory, env=env, + stdout=stdout_pipe, stderr=stderr_pipe) + except Exception as e: + ui.logger(__name__).warn("\nERROR WHILE CALLING \'" + make_cmd + ".exe\' WITH EXCEPTION \'"+str(e)+"\'.") + if not os.environ.get('PROS_TOOLCHAIN'): + ui.logger(__name__).warn("\nPROS TOOLCHAIN NOT FOUND! PLEASE ENSURE THE TOOLCHAIN IS INSTALLED CORRECTLY") + stdout_pipe.close() + stderr_pipe.close() + sys.exit() + stdout_pipe.close() + stderr_pipe.close() + process.wait() return process.returncode def make_scan_build(self, build_args: Tuple[str], cdb_file: Optional[Union[str, io.IOBase]] = None, @@ -269,7 +284,16 @@ def libscanbuild_capture(args: argparse.Namespace) -> Tuple[int, Iterable[Compil else: pipe = subprocess.DEVNULL logger(__name__).debug(self.directory) - exit_code = run_build(args.build, env=environment, stdout=pipe, stderr=pipe, cwd=self.directory) + exit_code=None + try: + exit_code = run_build(args.build, env=environment, stdout=pipe, stderr=pipe, cwd=self.directory) + except Exception as e: + ui.logger(__name__).warn("\nERROR WHILE CALLING \'" + make_cmd + ".exe\' WITH EXCEPTION \'"+str(e)+"\'.") + if not os.environ.get('PROS_TOOLCHAIN'): + ui.logger(__name__).warn("\nPROS TOOLCHAIN NOT FOUND! PLEASE ENSURE THE TOOLCHAIN IS INSTALLED CORRECTLY") + if not suppress_output: + pipe.close() + sys.exit() if not suppress_output: pipe.close() # read the intercepted exec calls From 59d206ed2ca0e267b897ef15470315c4d69a5e2b Mon Sep 17 00:00:00 2001 From: Benjamin Davis Date: Tue, 2 Nov 2021 15:49:45 -0400 Subject: [PATCH 4/4] Formats errors better. Uses error instead of warn. --- pros/conductor/project/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pros/conductor/project/__init__.py b/pros/conductor/project/__init__.py index be73c95a..a0d41a6f 100644 --- a/pros/conductor/project/__init__.py +++ b/pros/conductor/project/__init__.py @@ -231,9 +231,9 @@ def make(self, build_args: List[str]): process = subprocess.Popen(executable=make_cmd, args=[make_cmd, *build_args], cwd=self.directory, env=env, stdout=stdout_pipe, stderr=stderr_pipe) except Exception as e: - ui.logger(__name__).warn("\nERROR WHILE CALLING \'" + make_cmd + ".exe\' WITH EXCEPTION \'"+str(e)+"\'.") if not os.environ.get('PROS_TOOLCHAIN'): - ui.logger(__name__).warn("\nPROS TOOLCHAIN NOT FOUND! PLEASE ENSURE THE TOOLCHAIN IS INSTALLED CORRECTLY") + ui.logger(__name__).warn("PROS toolchain not found! Please ensure the toolchain is installed correctly and your environment variables are set properly.\n") + ui.logger(__name__).error(f"ERROR WHILE CALLING '{make_cmd}.exe' WITH EXCEPTION: {str(e)}\n") stdout_pipe.close() stderr_pipe.close() sys.exit() @@ -288,9 +288,9 @@ def libscanbuild_capture(args: argparse.Namespace) -> Tuple[int, Iterable[Compil try: exit_code = run_build(args.build, env=environment, stdout=pipe, stderr=pipe, cwd=self.directory) except Exception as e: - ui.logger(__name__).warn("\nERROR WHILE CALLING \'" + make_cmd + ".exe\' WITH EXCEPTION \'"+str(e)+"\'.") if not os.environ.get('PROS_TOOLCHAIN'): - ui.logger(__name__).warn("\nPROS TOOLCHAIN NOT FOUND! PLEASE ENSURE THE TOOLCHAIN IS INSTALLED CORRECTLY") + ui.logger(__name__).warn("PROS toolchain not found! Please ensure the toolchain is installed correctly and your environment variables are set properly.\n") + ui.logger(__name__).error(f"ERROR WHILE CALLING '{make_cmd}.exe' WITH EXCEPTION: {str(e)}\n") if not suppress_output: pipe.close() sys.exit()