def __enter__(self): now_us = monotonic_time_nanos() / 1000 self._add_trace_event( "buck-launcher", self.name, _TraceEventPhases.BEGIN, self.pid, 1, now_us, self.args, )
def __exit__(self, x_type, x_value, x_traceback): now_us = monotonic_time_nanos() / 1000 self._add_trace_event( "buck-launcher", self.name, _TraceEventPhases.END, self.pid, 1, now_us, self.args, )
def launch_buckd(self, java_path, jvm_args, buck_version_uid=None): with Tracing("BuckTool.launch_buckd"): setup_watchman_watch() if buck_version_uid is None: buck_version_uid = self._get_buck_version_uid() self._buck_project.create_buckd_dir() # Override self._tmp_dir to a long lived directory. buckd_tmp_dir = self._buck_project.create_buckd_tmp_dir() ngserver_output_path = os.path.join(buckd_tmp_dir, "ngserver-out") """ Use SoftRefLRUPolicyMSPerMB for immediate GC of javac output. Set timeout to 60s (longer than the biggest GC pause seen for a 2GB heap) and GC target to 15s. This means that the GC has to miss its target by 100% or many 500ms heartbeats must be missed before a client disconnection occurs. Specify port 0 to allow Nailgun to find an available port, then parse the port number out of the first log entry. """ command = ["buckd"] extra_default_options = [ "-Dbuck.is_buckd=true", "-Dbuck.buckd_launch_time_nanos={0}".format( monotonic_time_nanos()), "-Dfile.encoding=UTF-8", "-XX:MaxGCPauseMillis={0}".format(GC_MAX_PAUSE_TARGET), "-XX:SoftRefLRUPolicyMSPerMB=0", # Stop Java waking up every 50ms to collect thread # statistics; doing it once every five seconds is much # saner for a long-lived daemon. "-XX:PerfDataSamplingInterval=5000", # Do not touch most signals "-Xrs", # Likewise, waking up once per second just in case # there's some rebalancing to be done is silly. "-XX:+UnlockDiagnosticVMOptions", "-XX:GuaranteedSafepointInterval=5000", "-Djava.io.tmpdir={0}".format(buckd_tmp_dir), "-Dcom.facebook.nailgun.NGServer.outputPath={0}".format( ngserver_output_path), "-XX:+UseG1GC", "-XX:MaxHeapFreeRatio=40", ] command.extend(extra_default_options) command.extend(jvm_args) command.append( "com.facebook.buck.cli.bootstrapper.ClassLoaderBootstrapper") command.append("com.facebook.buck.cli.BuckDaemon") command.append(self._buck_project.get_buckd_transport_address()) command.append("{0}".format(BUCKD_CLIENT_TIMEOUT_MILLIS)) buckd_transport_file_path = ( self._buck_project.get_buckd_transport_file_path()) if os.name == "nt": # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx#DETACHED_PROCESS DETACHED_PROCESS = 0x00000008 creationflags = DETACHED_PROCESS # do not redirect output for Windows as it deadlocks stdin = None stdout = None stderr = None close_fds = True else: """ Change the process group of the child buckd process so that when this script is interrupted, it does not kill buckd. """ creationflags = 0 stdin = open(os.devnull, mode="r") stdout = open(self._buck_project.get_buckd_stdout(), mode="w+b", buffering=0) stderr = open(self._buck_project.get_buckd_stderr(), mode="w+b", buffering=0) close_fds = False process = subprocess.Popen( command, executable=java_path, cwd=self._buck_project.root, env=self._environ_for_buck(), creationflags=creationflags, close_fds=close_fds, stdin=stdin, stdout=stdout, stderr=stderr, ) self._buck_project.save_buckd_version(buck_version_uid) self._buck_project.save_buckd_jvm_args( self._get_java_args(buck_version_uid)) # Give Java some time to create the listening socket. wait_seconds = 0.01 repetitions = int(BUCKD_STARTUP_TIMEOUT_MILLIS / 1000.0 / wait_seconds) for _idx in range(repetitions): if transport_exists(buckd_transport_file_path): break time.sleep(wait_seconds) if not transport_exists(buckd_transport_file_path): return False returncode = process.poll() # If the process has exited then daemon failed to start if returncode is not None: return False # Save pid of running daemon self._buck_project.save_buckd_pid(process.pid) logging.info("Buck daemon started.") return True