def run_damon(target, is_target_cmd, init_regions, attrs, old_attrs): if os.path.isfile(attrs.rfile_path): os.rename(attrs.rfile_path, attrs.rfile_path + '.old') if attrs.apply(): print('attributes (%s) failed to be applied' % attrs) cleanup_exit(old_attrs, -1) print('# damon attrs: %s %s' % (attrs.attr_str(), attrs.record_str())) for line in attrs.schemes.split('\n'): print('# scheme: %s' % line) if is_target_cmd: p = subprocess.Popen(target, shell=True, executable='/bin/bash') target = p.pid if _damon.set_target(target, init_regions): print('target setting (%s, %s) failed' % (target, init_regions)) cleanup_exit(old_attrs, -2) if _damon.turn_damon('on'): print('could not turn on damon' % target) cleanup_exit(old_attrs, -3) while not _damon.is_damon_running(): sleep(1) print('Press Ctrl+C to stop') if is_target_cmd: p.wait() while True: # damon will turn it off by itself if the target tasks are terminated. if not _damon.is_damon_running(): break time.sleep(1) cleanup_exit(old_attrs, 0)
def cleanup_exit(orig_attrs, exit_code): if _damon.is_damon_running(): if _damon.turn_damon('off'): print('failed to turn damon off!') while _damon.is_damon_running(): sleep(1) if orig_attrs: if orig_attrs.apply(): print('original attributes (%s) restoration failed!' % orig_attrs) exit(exit_code)
def cleanup_exit(orig_attrs, exit_code): if perf_pipe: perf_pipe.send_signal(signal.SIGINT) perf_pipe.wait() subprocess.call('perf script -i \'%s\' > \'%s\'' % (rfile_path + '.perf.data', rfile_path), shell=True, executable='/bin/bash') if _damon.is_damon_running(): if _damon.turn_damon('off'): print('failed to turn damon off!') while _damon.is_damon_running(): time.sleep(1) if orig_attrs: if orig_attrs.apply(): print('original attributes (%s) restoration failed!' % orig_attrs) exit(exit_code)
def do_record(target, is_target_cmd, init_regions, attrs, old_attrs, pidfd, timeout): global perf_pipe global rfile_path rfile_path = attrs.rfile_path if os.path.isfile(attrs.rfile_path): os.rename(attrs.rfile_path, attrs.rfile_path + '.old') if attrs.apply(): print('attributes (%s) failed to be applied' % attrs) cleanup_exit(old_attrs, -1) print('# damon attrs: %s %s' % (attrs.attr_str(), attrs.record_str())) if is_target_cmd: p = subprocess.Popen(target, shell=True, executable='/bin/bash') target = p.pid if pidfd: fd = pidfd_open(int(target)) if fd < 0: print('failed getting pidfd of %s: %s' % (target, fd)) cleanup_exit(old_attrs, -1) # NOTE: The race is still possible because the pid might be already # reused before above pidfd_open() returned. Eliminating the race is # impossible unless we drop the pid support. This option handling is # only for reference of the pidfd usage. target = 'pidfd %s' % fd if _damon.set_target(target, init_regions): print('target setting (%s, %s) failed' % (target, init_regions)) cleanup_exit(old_attrs, -2) if _damon.turn_damon('on'): print('could not turn on damon' % target) cleanup_exit(old_attrs, -3) while not _damon.is_damon_running(): time.sleep(1) if not _damon.feature_supported('record'): perf_pipe = subprocess.Popen( 'perf record -e damon:damon_aggregated -a -o \'%s\'' % (attrs.rfile_path + '.perf.data'), shell=True, executable='/bin/bash') print('Press Ctrl+C to stop') wait_start = datetime.datetime.now() if is_target_cmd: try: p.wait(timeout=timeout) except subprocess.TimeoutExpired: p.kill() while True: if not _damon.is_damon_running(): break if timeout and ( (datetime.datetime.now() - wait_start).total_seconds() > timeout): break time.sleep(1) if pidfd: os.close(fd) cleanup_exit(old_attrs, 0)