class GoApp: def __init__(self, root_path): self.root_path = root_path self.proc = None self.proc_start = 0 self.goroot = os.path.join( up(__file__, 5), "goroot") if not os.path.isdir(self.goroot): raise Exception('no goroot found at ' + self.goroot) for bin in os.listdir(os.path.join(self.goroot, 'bin')): if len(bin) == 2 and bin[1] == 'g': self.arch = bin[0] break if not self.arch: raise Exception('bad goroot: no compiler found') atexit.register(self.cleanup) def cleanup(self): if self.proc: os.kill(self.proc.pid, signal.SIGTERM) def make_and_run(self, env): app_files = find_app_files(self.root_path) go_files, go_mtime = find_go_files_mtime(app_files) if not go_files: raise Exception('no .go files in %s', self.root_path) app_mtime = max(app_files.values()) bin_name, bin_mtime = os.path.join(GAB_WORK_DIR, GO_APP_NAME), 0 try: bin_mtime = os.stat(bin_name)[stat.ST_MTIME] except: pass rebuild, restart = False, False if go_mtime >= bin_mtime: rebuild, restart = True, True elif app_mtime > self.proc_start: restart = True if restart and self.proc: os.kill(self.proc.pid, signal.SIGTERM) self.proc.wait() self.proc = None if rebuild: self.build(go_files) if not self.proc or self.proc.poll() is not None: logging.info('running ' + GO_APP_NAME) limited_env = { 'PWD': self.root_path, 'TZ': 'UTC', } for k, v in env.items(): if ENV_PASSTHROUGH.match(k): limited_env[k] = v self.proc_start = app_mtime self.proc = subprocess.Popen([bin_name, '-addr_http', 'unix:' + SOCKET_HTTP, '-addr_api', 'unix:' + SOCKET_API], stderr=subprocess.PIPE, cwd=self.root_path, env=limited_env) tee = Tee(self.proc.stderr, sys.stderr) tee.start() wait_until_go_app_ready(self.proc, tee) def build(self, go_files): logging.info('building ' + GO_APP_NAME) if not os.path.exists(GAB_WORK_DIR): os.makedirs(GAB_WORK_DIR) gab_argv = [ os.path.join(self.goroot, 'bin', 'go-app-builder'), '-app_base', self.root_path, '-arch', self.arch, '-binary_name', GO_APP_NAME, '-dynamic', '-goroot', self.goroot, '-unsafe', '-work_dir', GAB_WORK_DIR] + go_files try: p = subprocess.Popen(gab_argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env={}) gab_retcode = p.wait() except Exception, e: raise Exception('cannot call go-app-builder', e) if gab_retcode != 0: raise dev_appserver.CompileError(p.stdout.read() + '\n' + p.stderr.read())
raise dev_appserver.CompileError(p.stdout.read() + '\n' + p.stderr.read()) def extras_hash(self, go_files): logging.info('checking extra files') gab_argv = self._gab_args() + ['-print_extras_hash'] + go_files try: p = subprocess.Popen(gab_argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env={}) gab_retcode = p.wait() except Exception, e: raise Exception('cannot call go-app-builder', e) if gab_retcode != 0: raise dev_appserver.CompileError(p.stderr.read()) return p.stdout.read() OldSigTermHandler = None def SigTermHandler(signum, frame): if GO_APP: GO_APP.cleanup() if OldSigTermHandler: OldSigTermHandler(signum, frame) def execute_go_cgi(root_path, config, handler_path, cgi_path, env, infile, outfile):
class GoApp: def __init__(self, root_path): self.root_path = root_path self.proc = None self.proc_start = 0 self.last_extras_hash = None self.goroot = os.path.join(up(__file__, 5), 'goroot') if not os.path.isdir(self.goroot): raise Exception('no goroot found at ' + self.goroot) self.arch = None arch_map = { 'arm': '5', 'amd64': '6', '386': '8', } for p in os.listdir(os.path.join(self.goroot, 'pkg', 'tool')): if '_' not in p: continue arch = p.split('_', 1)[1] if arch in arch_map: self.arch = arch_map[arch] break if not self.arch: raise Exception('bad goroot: no compiler found') atexit.register(self.cleanup) def cleanup(self): if self.proc: quiet_kill(self.proc.pid) self.proc = None def make_and_run(self, env): app_files = find_app_files(self.root_path) go_files, go_mtime = find_go_files_mtime(app_files) if not go_files: raise Exception('no .go files in %s', self.root_path) app_mtime = max(app_files.values()) bin_name, bin_mtime = os.path.join(GAB_WORK_DIR, GO_APP_NAME), 0 try: bin_mtime = os.stat(bin_name)[stat.ST_MTIME] except: pass rebuild, restart = False, False if go_mtime >= bin_mtime: rebuild, restart = True, True elif app_mtime > self.proc_start: restart = True if not rebuild: h = self.extras_hash(go_files) if h != self.last_extras_hash: logging.info('extra-app files hash changed to %s; rebuilding', h) self.last_extras_hash = h rebuild, restart = True, True if restart and self.proc: quiet_kill(self.proc.pid) self.proc.wait() self.proc = None if rebuild: self.build(go_files) if not self.proc or self.proc.poll() is not None: logging.info('running %s, HTTP port = %d, API port = %d', GO_APP_NAME, GO_HTTP_PORT, GO_API_PORT) limited_env = { 'GOROOT': self.goroot, 'PWD': self.root_path, 'TZ': 'UTC', } for k, v in env.items(): if ENV_PASSTHROUGH.match(k): limited_env[k] = v for e in OS_ENV_PASSTHROUGH: if e in os.environ: limited_env[e] = os.environ[e] self.proc_start = app_mtime self.proc = subprocess.Popen([ bin_name, '-addr_http', 'tcp:127.0.0.1:%d' % GO_HTTP_PORT, '-addr_api', 'tcp:127.0.0.1:%d' % GO_API_PORT ], stderr=subprocess.PIPE, cwd=self.root_path, env=limited_env) tee = Tee(self.proc.stderr, sys.stderr) tee.start() wait_until_go_app_ready(self.proc, tee) def _gab_args(self): argv = [ os.path.join(self.goroot, 'bin', 'go-app-builder'), '-app_base', self.root_path, '-arch', self.arch, '-binary_name', GO_APP_NAME, '-dynamic', '-goroot', os.environ['GOROOT'], '-unsafe', '-work_dir', GAB_WORK_DIR, ] if 'GOPATH' in os.environ: argv.extend(['-gopath', os.environ['GOPATH']]) return argv def build(self, go_files): logging.info('building ' + GO_APP_NAME) if not os.path.exists(GAB_WORK_DIR): os.makedirs(GAB_WORK_DIR) gab_argv = self._gab_args() + go_files try: p = subprocess.Popen(gab_argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env={}) gab_retcode = p.wait() except Exception, e: raise Exception('cannot call go-app-builder', e) if gab_retcode != 0: raise dev_appserver.CompileError(p.stdout.read() + '\n' + p.stderr.read())
class GoApp: def __init__(self, root_path): self.root_path = root_path self.proc = None self.goroot = os.path.join(up(__file__, 5), "goroot") if not os.path.isdir(self.goroot): raise Exception('no goroot found at ' + self.goroot) for bin in os.listdir(os.path.join(self.goroot, 'bin')): if len(bin) == 2 and bin[1] == 'g': self.arch = bin[0] break if not self.arch: raise Exception('bad goroot: no compiler found') def make_and_run(self): go_files, go_mtime = find_go_files_mtime(self.root_path) if not go_files: raise Exception('no .go files in %s', self.root_path) app_name, app_mtime = os.path.join(GAB_WORK_DIR, GO_APP_NAME), 0 try: app_mtime = os.stat(app_name)[stat.ST_MTIME] except: pass if go_mtime >= app_mtime: if self.proc: os.kill(self.proc.pid, signal.SIGTERM) self.proc.wait() self.proc = None self.build(go_files, app_name) if not self.proc or self.proc.poll() is not None: logging.info('running ' + GO_APP_NAME) self.proc = subprocess.Popen([ app_name, '-addr_http', 'unix:' + SOCKET_HTTP, '-addr_api', 'unix:' + SOCKET_API ], cwd=self.root_path) wait_until_go_app_ready() def build(self, go_files, app_name): logging.info('building ' + GO_APP_NAME) if not os.path.exists(GAB_WORK_DIR): os.makedirs(GAB_WORK_DIR) gab_argv = [ os.path.join(self.goroot, 'bin', 'go-app-builder'), '-app_base', self.root_path, '-arch', self.arch, '-binary_name', GO_APP_NAME, '-dynamic', '-goroot', self.goroot, '-unsafe', '-work_dir', GAB_WORK_DIR ] + go_files try: p = subprocess.Popen(gab_argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE) gab_retcode = p.wait() except Exception, e: raise Exception('cannot call go-app-builder', e) if gab_retcode != 0: raise dev_appserver.CompileError(p.stdout.read() + '\n' + p.stderr.read())