def _pre_run_cleanup(self):
     """Common cleanup before running a testcase."""
     # Cleanup any existing application instances and user profile directories.
     # Cleaning up temp user profile directories. Should be done before calling
     # |get_command_line_for_application| call since that creates dependencies in
     # the profile folder.
     process_handler.terminate_stale_application_instances()
     shell.clear_temp_directory()
示例#2
0
def beat(previous_state, log_filename):
    """Run a cycle of heartbeat checks to ensure bot is running."""
    # Handle case when run_bot.py script is stuck. If yes, kill its process.
    task_end_time = tasks.get_task_end_time()
    if psutil and task_end_time and dates.time_has_expired(
            task_end_time, seconds=tasks.TASK_COMPLETION_BUFFER):

        # Get absolute path to |run_bot| script. We use this to identify unique
        # instances of bot running on a particular host.
        startup_scripts_directory = environment.get_startup_scripts_directory()
        bot_file_path = os.path.join(startup_scripts_directory, 'run_bot')

        for process in psutil.process_iter():
            try:
                command_line = ' '.join(process.cmdline())
            except (psutil.AccessDenied, psutil.NoSuchProcess, OSError):
                continue

            # Find the process running the main bot script.
            if bot_file_path not in command_line:
                continue

            process_id = process.pid
            logs.log('Killing stale bot (pid %d) which seems to have stuck.' %
                     process_id)
            try:
                process_handler.terminate_root_and_child_processes(process_id)
            except Exception:
                logs.log_error('Failed to terminate stale bot processes.')

        # Minor cleanup to avoid disk space issues on bot restart.
        process_handler.terminate_stale_application_instances()
        shell.clear_temp_directory()
        shell.clear_testcase_directories()

        # Concerned stale processes should be killed. Now, delete the stale task.
        tasks.track_task_end()

    # Figure out when the log file was last modified.
    try:
        current_state = str(os.path.getmtime(log_filename))
    except Exception:
        current_state = None

    # Only update the heartbeat if the log file was modified.
    if current_state and current_state != previous_state:
        # Try updating the heartbeat. If an error occurs, just
        # wait and return None.
        if not data_handler.update_heartbeat():
            return None
        # Heartbeat is successfully updated.

    return current_state
示例#3
0
def cleanup_task_state():
  """Cleans state before and after a task is executed."""
  # Cleanup stale processes.
  process_handler.cleanup_stale_processes()

  # Clear build urls, temp and testcase directories.
  shell.clear_build_urls_directory()
  shell.clear_crash_stacktraces_directory()
  shell.clear_testcase_directories()
  shell.clear_temp_directory()
  shell.clear_system_temp_directory()
  shell.clear_device_temp_directories()

  # Reset memory tool environment variables.
  environment.reset_current_memory_tool_options()

  # Call python's garbage collector.
  utils.python_gc()
示例#4
0
def update_source_code():
    """Updates source code files with latest version from appengine."""
    process_handler.cleanup_stale_processes()
    shell.clear_temp_directory()

    root_directory = environment.get_value('ROOT_DIR')
    temp_directory = environment.get_value('BOT_TMPDIR')
    temp_archive = os.path.join(temp_directory, 'clusterfuzz-source.zip')
    try:
        storage.copy_file_from(get_source_url(), temp_archive)
    except Exception:
        logs.log_error('Could not retrieve source code archive from url.')
        return

    try:
        file_list = archive.get_file_list(temp_archive)
        zip_archive = zipfile.ZipFile(temp_archive, 'r')
    except Exception:
        logs.log_error('Bad zip file.')
        return

    src_directory = os.path.join(root_directory, 'src')
    output_directory = os.path.dirname(root_directory)
    error_occurred = False
    normalized_file_set = set()
    for filepath in file_list:
        filename = os.path.basename(filepath)

        # This file cannot be updated on the fly since it is running as server.
        if filename == 'adb':
            continue

        absolute_filepath = os.path.join(output_directory, filepath)
        if os.path.altsep:
            absolute_filepath = absolute_filepath.replace(
                os.path.altsep, os.path.sep)

        if os.path.realpath(absolute_filepath) != absolute_filepath:
            continue

        normalized_file_set.add(absolute_filepath)
        try:
            file_extension = os.path.splitext(filename)[1]

            # Remove any .so files first before overwriting, as they can be loaded
            # in the memory of existing processes. Overwriting them directly causes
            # segfaults in existing processes (e.g. run.py).
            if file_extension == '.so' and os.path.exists(absolute_filepath):
                os.remove(absolute_filepath)

            # On Windows, to update DLLs (and native .pyd extensions), we rename it
            # first so that we can install the new version.
            if (environment.platform() == 'WINDOWS'
                    and file_extension in ['.dll', '.pyd']
                    and os.path.exists(absolute_filepath)):
                _rename_dll_for_update(absolute_filepath)
        except Exception:
            logs.log_error('Failed to remove or move %s before extracting new '
                           'version.' % absolute_filepath)

        try:
            extracted_path = zip_archive.extract(filepath, output_directory)
            external_attr = zip_archive.getinfo(filepath).external_attr
            mode = (external_attr >> 16) & 0o777
            mode |= 0o440
            os.chmod(extracted_path, mode)
        except:
            error_occurred = True
            logs.log_error('Failed to extract file %s from source archive.' %
                           filepath)

    zip_archive.close()

    if error_occurred:
        return

    clear_pyc_files(src_directory)
    clear_old_files(src_directory, normalized_file_set)

    local_manifest_path = os.path.join(root_directory,
                                       utils.LOCAL_SOURCE_MANIFEST)
    source_version = utils.read_data_from_file(
        local_manifest_path, eval_data=False).decode('utf-8').strip()
    logs.log('Source code updated to %s.' % source_version)