Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/tosu/src/instances/lazerInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ export class LazerInstance extends AbstractInstance {

override async initiate() {
try {
const startTime = this.process.getStartTime();
const age = startTime > 0 ? Date.now() - startTime : 0;
const waitMs = Math.max(0, 15 * 1000 - age);

if (waitMs > 0) {
wLogger.info(
`%${ClientType[this.client]}%`,
`Waiting %${(waitMs / 1000).toFixed(1)}s% for lazer startup before reading memory...`
);
await sleep(waitMs);
}

const cacheFolder = getCachePath();
if (!fs.existsSync(cacheFolder))
await fsp.mkdir(cacheFolder, { recursive: true });
Expand Down
2 changes: 1 addition & 1 deletion packages/tosu/src/memory/lazer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ export class LazerMemory extends AbstractMemory<LazerPatternData> {

private scanPatterns: ScanPatterns = {
scalingContainerTargetDrawSize: {
pattern: '00 00 80 44 00 00 40 44',
pattern: '01 01 00 00 00 00 80 44 00 00 40 44',
offset: 0,
nonZeroMask: false
}
Expand Down
12 changes: 12 additions & 0 deletions packages/tsprocess/lib/functions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,17 @@ Napi::Value is_process_64bit(const Napi::CallbackInfo &args) {
return Napi::Boolean::New(env, memory::is_process_64bit(process_id));
}

Napi::Value get_process_start_time(const Napi::CallbackInfo &args) {
Napi::Env env = args.Env();
if (args.Length() < 1) {
Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
return env.Null();
}

auto handle = reinterpret_cast<void *>(args[0].As<Napi::Number>().Int64Value());
return Napi::Number::New(env, static_cast<double>(memory::get_process_start_time(handle)));
}

Napi::Value get_process_path(const Napi::CallbackInfo &args) {
Napi::Env env = args.Env();
if (args.Length() < 1) {
Expand Down Expand Up @@ -560,6 +571,7 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
exports["closeHandle"] = Napi::Function::New(env, close_handle);
exports["findProcesses"] = Napi::Function::New(env, find_processes);
exports["isProcessExist"] = Napi::Function::New(env, is_process_exist);
exports["getProcessStartTime"] = Napi::Function::New(env, get_process_start_time);
exports["isProcess64bit"] = Napi::Function::New(env, is_process_64bit);
exports["getProcessPath"] = Napi::Function::New(env, get_process_path);
exports["getProcessCommandLine"] = Napi::Function::New(env, get_process_command_line);
Expand Down
1 change: 1 addition & 0 deletions packages/tsprocess/lib/memory/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ void *open_process(uint32_t id);
void close_handle(void *handle);
bool is_process_64bit(uint32_t id);
bool is_process_exist(void *process);
uint64_t get_process_start_time(void *process);
std::string get_process_path(void *process);
std::string get_process_command_line(void *process);
std::string get_process_cwd(void *process);
Expand Down
12 changes: 12 additions & 0 deletions packages/tsprocess/lib/memory/memory_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,18 @@ bool memory::is_process_exist(void *process) {
return true;
}

// Returns the process creation time as unix epoch milliseconds, or 0 on failure.
// /proc/<pid> is created when the process starts, so its ctime approximates it.
uint64_t memory::get_process_start_time(void *process) {
const auto pid = reinterpret_cast<uintptr_t>(process);
struct stat sts;
const auto proc_path = "/proc/" + std::to_string(pid);
if (stat(proc_path.c_str(), &sts) != 0) {
return 0;
}
return static_cast<uint64_t>(sts.st_ctime) * 1000ULL;
}

bool memory::is_process_64bit(uint32_t id) {
const auto exe_path = "/proc/" + std::to_string(id) + "/exe";

Expand Down
21 changes: 21 additions & 0 deletions packages/tsprocess/lib/memory/memory_windows.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,27 @@ bool memory::is_process_exist(void *handle) {
return false;
}

// Returns the process creation time as unix epoch milliseconds, or 0 on failure.
uint64_t memory::get_process_start_time(void *handle) {
FILETIME creation{}, exit{}, kernel{}, user{};
if (!GetProcessTimes(handle, &creation, &exit, &kernel, &user)) {
return 0;
}

ULARGE_INTEGER ticks;
ticks.LowPart = creation.dwLowDateTime;
ticks.HighPart = creation.dwHighDateTime;

// FILETIME counts 100ns intervals since 1601-01-01. 116444736000000000 is the
// interval count between 1601 and the unix epoch (1970-01-01).
constexpr uint64_t epochDelta = 116444736000000000ULL;
if (ticks.QuadPart < epochDelta) {
return 0;
}

return (ticks.QuadPart - epochDelta) / 10000ULL;
}

bool memory::is_process_64bit(uint32_t id) {
HANDLE process_handle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, id);
BOOL is_wow64 = FALSE;
Expand Down
4 changes: 4 additions & 0 deletions packages/tsprocess/src/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ export class Process {
return ProcessUtils.isProcessExist(handle);
}

getStartTime(): number {
return ProcessUtils.getProcessStartTime(this.handle);
}

static isProcess64bit(pid: number): boolean {
return ProcessUtils.isProcess64bit(pid);
}
Expand Down
Loading