From: Sebastian Lackner sebastian@fds-team.de
Based on a patch by Ray Hinchliffe ray@pobox.co.uk.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=20230 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- The only applications associated with this patch, and the others in the series, are essentially system process monitors. Accordingly, it's not really providing anything useful over host utilities such as ps(1).
This patch helps System Information Viewer, and the other two in the series help Process Hacker.
I have omitted NtQueryInformationProcess(ProcessTimes), since the obvious solution needs the server to pass back more data than it currently can, and I don't know what the preferred way to handle that is.
dlls/ntdll/thread.c | 84 ++++++++++++++++++++++++++++++++++++--------- server/protocol.def | 2 ++ server/thread.c | 2 ++ 3 files changed, 71 insertions(+), 17 deletions(-)
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index f9ea9203ed..7ec4a359ec 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -22,7 +22,10 @@ #include "wine/port.h"
#include <assert.h> +#include <errno.h> #include <stdarg.h> +#include <string.h> +#include <stdio.h> #include <limits.h> #include <sys/types.h> #ifdef HAVE_SYS_MMAN_H @@ -764,6 +767,59 @@ NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int fla return ret; }
+#ifdef linux +static BOOL get_thread_times(int unix_pid, int unix_tid, LARGE_INTEGER *kernel_time, LARGE_INTEGER *user_time) +{ + unsigned long clocks_per_sec = sysconf(_SC_CLK_TCK); + unsigned long usr, sys; + const char *pos; + char buf[512]; + FILE *f; + int i; + + sprintf( buf, "/proc/%u/task/%u/stat", unix_pid, unix_tid ); + if (!(f = fopen( buf, "r" ))) + { + ERR("Failed to open %s: %s\n", buf, strerror(errno)); + return FALSE; + } + + pos = fgets( buf, sizeof(buf), f ); + fclose( f ); + + /* the process name is printed unescaped, so we have to skip to the last ')' + * to avoid misinterpreting the string */ + if (pos) pos = strrchr( pos, ')' ); + if (pos) pos = strchr( pos + 1, ' ' ); + if (pos) pos++; + + /* skip over the following fields: state, ppid, pgid, sid, tty_nr, tty_pgrp, + * task->flags, min_flt, cmin_flt, maj_flt, cmaj_flt */ + for (i = 0; i < 11 && pos; i++) + { + pos = strchr( pos + 1, ' ' ); + if (pos) pos++; + } + + /* the next two values are user and system time */ + if (pos && (sscanf( pos, "%lu %lu", &usr, &sys ) == 2)) + { + kernel_time->QuadPart = (ULONGLONG)sys * 10000000 / clocks_per_sec; + user_time->QuadPart = (ULONGLONG)usr * 10000000 / clocks_per_sec; + return TRUE; + } + + ERR("Failed to parse %s\n", debugstr_a(buf)); + return FALSE; +} +#else +static BOOL get_thread_times(int unix_pid, int unix_tid, LARGE_INTEGER *kernel_time, LARGE_INTEGER *user_time) +{ + static int once; + if (!once++) FIXME("not implemented on this platform\n"); + return FALSE; +} +#endif
/*********************************************************************** * NtSetContextThread (NTDLL.@) @@ -859,6 +915,7 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class, case ThreadTimes: { KERNEL_USER_TIMES kusrt; + int unix_pid, unix_tid;
SERVER_START_REQ( get_thread_times ) { @@ -868,15 +925,21 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class, { kusrt.CreateTime.QuadPart = reply->creation_time; kusrt.ExitTime.QuadPart = reply->exit_time; + unix_pid = reply->unix_pid; + unix_tid = reply->unix_tid; } } SERVER_END_REQ; if (status == STATUS_SUCCESS) { - /* We call times(2) for kernel time or user time */ - /* We can only (portably) do this for the current thread */ - if (handle == GetCurrentThread()) + BOOL ret = FALSE; + + kusrt.KernelTime.QuadPart = kusrt.UserTime.QuadPart = 0; + if (unix_pid != -1 && unix_tid != -1) + ret = get_thread_times( unix_pid, unix_tid, &kusrt.KernelTime, &kusrt.UserTime ); + if (!ret && handle == GetCurrentThread()) { + /* fall back to process times */ struct tms time_buf; long clocks_per_sec = sysconf(_SC_CLK_TCK);
@@ -884,20 +947,7 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class, kusrt.KernelTime.QuadPart = (ULONGLONG)time_buf.tms_stime * 10000000 / clocks_per_sec; kusrt.UserTime.QuadPart = (ULONGLONG)time_buf.tms_utime * 10000000 / clocks_per_sec; } - else - { - static BOOL reported = FALSE; - - kusrt.KernelTime.QuadPart = 0; - kusrt.UserTime.QuadPart = 0; - if (reported) - TRACE("Cannot get kerneltime or usertime of other threads\n"); - else - { - FIXME("Cannot get kerneltime or usertime of other threads\n"); - reported = TRUE; - } - } + if (data) memcpy( data, &kusrt, min( length, sizeof(kusrt) )); if (ret_len) *ret_len = min( length, sizeof(kusrt) ); } diff --git a/server/protocol.def b/server/protocol.def index 632c996dc0..0e4c6e79bc 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -966,6 +966,8 @@ struct rawinput_device @REPLY timeout_t creation_time; /* thread creation time */ timeout_t exit_time; /* thread exit time */ + int unix_pid; /* thread native pid */ + int unix_tid; /* thread native pid */ @END
diff --git a/server/thread.c b/server/thread.c index e2bfa50c7b..3cf447b1a0 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1554,6 +1554,8 @@ DECL_HANDLER(get_thread_times) { reply->creation_time = thread->creation_time; reply->exit_time = thread->exit_time; + reply->unix_pid = thread->unix_pid; + reply->unix_tid = thread->unix_tid;
release_object( thread ); }
From: Michael Müller michael@fds-team.de
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/nt.c | 42 +++++++++++++++++++++++++---------------- dlls/ntdll/ntdll_misc.h | 1 + dlls/ntdll/thread.c | 4 ++-- server/protocol.def | 1 + server/snapshot.c | 1 + 5 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index 7758f19a16..9b5bbd09ee 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -2650,6 +2650,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( len = 0; while (ret == STATUS_SUCCESS) { + int unix_pid = -1; SERVER_START_REQ( next_process ) { req->handle = wine_server_obj_handle( hSnap ); @@ -2657,6 +2658,8 @@ NTSTATUS WINAPI NtQuerySystemInformation( wine_server_set_reply( req, procname, sizeof(procname)-sizeof(WCHAR) ); if (!(ret = wine_server_call( req ))) { + unix_pid = reply->unix_pid; + /* Make sure procname is 0 terminated */ procname[wine_server_reply_size(reply) / sizeof(WCHAR)] = 0;
@@ -2693,7 +2696,7 @@ NTSTATUS WINAPI NtQuerySystemInformation( } } SERVER_END_REQ; - + if (ret != STATUS_SUCCESS) { if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS; @@ -2708,31 +2711,38 @@ NTSTATUS WINAPI NtQuerySystemInformation( i = j = 0; while (ret == STATUS_SUCCESS) { + int unix_tid, pid, tid, base_pri, delta_pri; SERVER_START_REQ( next_thread ) { req->handle = wine_server_obj_handle( hSnap ); req->reset = (j == 0); if (!(ret = wine_server_call( req ))) { + unix_tid = reply->unix_tid; + pid = reply->pid; + tid = reply->tid; + base_pri = reply->base_pri; + delta_pri = reply->delta_pri; j++; - if (UlongToHandle(reply->pid) == spi->UniqueProcessId) - { - /* ftKernelTime, ftUserTime, ftCreateTime; - * dwTickCount, dwStartAddress - */ - - memset(&spi->ti[i], 0, sizeof(spi->ti)); - - spi->ti[i].CreateTime.QuadPart = 0xdeadbeef; - spi->ti[i].ClientId.UniqueProcess = UlongToHandle(reply->pid); - spi->ti[i].ClientId.UniqueThread = UlongToHandle(reply->tid); - spi->ti[i].dwCurrentPriority = reply->base_pri + reply->delta_pri; - spi->ti[i].dwBasePriority = reply->base_pri; - i++; - } } } SERVER_END_REQ; + + if (!ret) + { + if (UlongToHandle(pid) == spi->UniqueProcessId) + { + memset(&spi->ti[i], 0, sizeof(spi->ti)); + + spi->ti[i].CreateTime.QuadPart = 0xdeadbeef; + spi->ti[i].ClientId.UniqueProcess = UlongToHandle(pid); + spi->ti[i].ClientId.UniqueThread = UlongToHandle(tid); + spi->ti[i].dwCurrentPriority = base_pri + delta_pri; + spi->ti[i].dwBasePriority = base_pri; + get_thread_times(unix_pid, unix_tid, &spi->ti[i].KernelTime, &spi->ti[i].UserTime); + i++; + } + } } if (ret == STATUS_NO_MORE_FILES) ret = STATUS_SUCCESS;
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index e9a3230e81..64163a175c 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -56,6 +56,7 @@ struct drive_info
extern NTSTATUS close_handle( HANDLE ) DECLSPEC_HIDDEN; extern ULONG_PTR get_system_affinity_mask(void) DECLSPEC_HIDDEN; +extern BOOL get_thread_times(int unix_pid, int unix_tid, LARGE_INTEGER *kernel_time, LARGE_INTEGER *user_time) DECLSPEC_HIDDEN;
/* exceptions */ extern void wait_suspend( CONTEXT *context ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 7ec4a359ec..c0821bcf13 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -768,7 +768,7 @@ NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int fla }
#ifdef linux -static BOOL get_thread_times(int unix_pid, int unix_tid, LARGE_INTEGER *kernel_time, LARGE_INTEGER *user_time) +BOOL get_thread_times(int unix_pid, int unix_tid, LARGE_INTEGER *kernel_time, LARGE_INTEGER *user_time) { unsigned long clocks_per_sec = sysconf(_SC_CLK_TCK); unsigned long usr, sys; @@ -813,7 +813,7 @@ static BOOL get_thread_times(int unix_pid, int unix_tid, LARGE_INTEGER *kernel_t return FALSE; } #else -static BOOL get_thread_times(int unix_pid, int unix_tid, LARGE_INTEGER *kernel_time, LARGE_INTEGER *user_time) +BOOL get_thread_times(int unix_pid, int unix_tid, LARGE_INTEGER *kernel_time, LARGE_INTEGER *user_time) { static int once; if (!once++) FIXME("not implemented on this platform\n"); diff --git a/server/protocol.def b/server/protocol.def index 0e4c6e79bc..57fdf862a7 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1913,6 +1913,7 @@ enum char_info_mode thread_id_t tid; /* thread id */ int base_pri; /* base priority */ int delta_pri; /* delta priority */ + int unix_tid; /* thread native pid */ @END
diff --git a/server/snapshot.c b/server/snapshot.c index a0f2ea17a3..bdceaef530 100644 --- a/server/snapshot.c +++ b/server/snapshot.c @@ -150,6 +150,7 @@ static int snapshot_next_thread( struct snapshot *snapshot, struct next_thread_r reply->tid = get_thread_id( ptr->thread ); reply->base_pri = ptr->priority; reply->delta_pri = 0; /* FIXME */ + reply->unix_tid = ptr->thread->unix_tid; return 1; }
From: Michael Müller michael@fds-team.de
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/nt.c | 2 ++ dlls/ntdll/thread.c | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index 9b5bbd09ee..5ff9c4bebf 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -2703,6 +2703,8 @@ NTSTATUS WINAPI NtQuerySystemInformation( break; }
+ get_thread_times(unix_pid, -1, &spi->KernelTime, &spi->UserTime); + if (Length >= len) { int i, j; diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index c0821bcf13..83bfeb40d0 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -777,7 +777,10 @@ BOOL get_thread_times(int unix_pid, int unix_tid, LARGE_INTEGER *kernel_time, LA FILE *f; int i;
- sprintf( buf, "/proc/%u/task/%u/stat", unix_pid, unix_tid ); + if (unix_tid == -1) + sprintf( buf, "/proc/%u/stat", unix_pid ); + else + sprintf( buf, "/proc/%u/task/%u/stat", unix_pid, unix_tid ); if (!(f = fopen( buf, "r" ))) { ERR("Failed to open %s: %s\n", buf, strerror(errno));
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=72669
Your paranoid android.
=== debiant (32 bit report) ===
ntdll: Unhandled exception: page fault on write access to 0x00000030 in 32-bit code (0x7bcbaeef).
Report validation errors: ntdll:info crashed (c0000005)
=== debiant (32 bit Chinese:China report) ===
ntdll: Unhandled exception: page fault on write access to 0x00000030 in 32-bit code (0x7bcbaeef).
Report validation errors: ntdll:info crashed (c0000005)
=== debiant (32 bit WoW report) ===
ntdll: Unhandled exception: page fault on write access to 0x00000030 in 32-bit code (0x7bcbaeef).
Report validation errors: ntdll:info crashed (c0000005)
=== debiant (64 bit WoW report) ===
ntdll: Unhandled exception: page fault on write access to 0x00000030 in 32-bit code (0x7bcbaeef).
Report validation errors: ntdll:info crashed (c0000005)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=72667
Your paranoid android.
=== debiant (32 bit WoW report) ===
ntdll: om.c:2133: Test failed: got 88