Update of /cvsroot/boost/boost/tools/jam/src
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv27919
Modified Files:
Tag: RC_1_34_0
execnt.c
Log Message:
Merge dialog-closing improvements from Bronek
Index: execnt.c
===================================================================
RCS file: /cvsroot/boost/boost/tools/jam/src/execnt.c,v
retrieving revision 1.24.2.2
retrieving revision 1.24.2.3
diff -u -d -r1.24.2.2 -r1.24.2.3
--- execnt.c 15 Jul 2006 05:56:54 -0000 1.24.2.2
+++ execnt.c 20 Jul 2006 06:29:34 -0000 1.24.2.3
@@ -915,6 +915,17 @@
return 0.0;
}
+static double
+creation_time(HANDLE process)
+{
+ FILETIME creation, exit, kernel, user, current;
+ if (GetProcessTimes(process, &creation, &exit, &kernel, &user))
+ {
+ return filetime_seconds(creation);
+ }
+ return 0.0;
+}
+
/* it's just stupidly silly that one has to do this! */
typedef struct PROCESS_BASIC_INFORMATION__ {
LONG ExitStatus;
@@ -998,7 +1009,10 @@
TerminateProcess(process,-2);
}
-int is_parent_child(DWORD parent, DWORD child)
+/* recursive check if first process is parent (directly or indirectly) of
+the latter one. Both processes are passed as process ids, not handles */
+static int
+is_parent_child(DWORD parent, DWORD child)
{
HANDLE process_snapshot_h = INVALID_HANDLE_VALUE;
@@ -1020,33 +1034,53 @@
{
if (pinfo.th32ProcessID == child)
{
- CloseHandle(process_snapshot_h);
- if (!stricmp(pinfo.szExeFile, "explorer.exe"))
+ /*
+ Unfortunately, process ids are not really unique. There might
+ be spurious "parent and child" relationship match between
+ two non-related processes if real parent process of a given
+ process has exited (while child process kept running as an
+ "orphan") and the process id of such parent process has been
+ reused by internals of the operating system when creating
+ another process. Thus additional check is needed - process
+ creation time. */
+ double tchild = 0.0;
+ double tparent = 0.0;
+ HANDLE hchild = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,
pinfo.th32ProcessID);
+ if (hchild != 0)
{
- /* explorer.exe is orphaned and process_id of its parent
may
- accidentally match process_id of process we are after. We
must not
- close dialog boxes displayed by children of explorer.exe
even
- though (thanks to its parent process id) it might appear
to be
- our child. This is not very reliable - there might be more
- orphaned processes or shell might be something else than
- explorer.exe, but this is most common and important
scenario */
- return 0;
+ HANDLE hparent = OpenProcess(PROCESS_QUERY_INFORMATION,
FALSE, pinfo.th32ParentProcessID);
+ if (hparent != 0)
+ {
+ tchild = creation_time(hchild);
+ tparent = creation_time(hparent);
+
+ CloseHandle(hparent);
+ }
+ CloseHandle(hchild);
}
- if (!stricmp(pinfo.szExeFile, "csrss.exe"))
+ CloseHandle(process_snapshot_h);
+
+ /* was child created before alleged parent? */
+ if (tchild == 0.0 || tparent == 0.0 || tchild < tparent)
+ return 0;
+
+ /* csrss.exe may display message box like following:
+ xyz.exe - Unable To Locate Component
+ This application has failed to start because
+ boost_foo-bar.dll was not found. Re-installing the
+ application may fix the problem
+ This actually happens when starting test process that depends
+ on a dynamic library which failed to build. We want to
+ automatically close these message boxes even though csrss.exe
+ is not our child process. We may depend on the fact that (in
+ all current versions of Windows) csrss.exe is indirectly
+ child of System process, which always has process id == 4 */
+ if (stricmp(pinfo.szExeFile, "csrss.exe") == 0)
{
- /* csrss.exe may display message box like following:
- xyz.exe - Unable To Locate Component
- This application has failed to start because
boost_foo-bar.dll
- was not found. Re-installing the application may fix
the problem
- This actually happens when starting test process that
depends on
- dynamic library which failed to build. We want to
automatically
- close these message boxes even though csrss.exe is not our
- child process. We may depend on the fact that (in all
current
- versions of Windows) csrss.exe is indirectly child of
System which
- always has process id == 4 */
if (is_parent_child(4, pinfo.th32ParentProcessID))
return 1;
}
+
return is_parent_child(parent, pinfo.th32ParentProcessID);
}
}
@@ -1057,31 +1091,35 @@
return 0;
}
-int related(DWORD d, DWORD p)
-{
- return is_parent_child(d, p);
-}
-
typedef struct PROCESS_HANDLE_ID {HANDLE h; DWORD pid;} PROCESS_HANDLE_ID;
-BOOL CALLBACK window_enum(HWND hwnd, LPARAM lParam)
+/* This function is called by the operating system for each topmost window. */
+BOOL CALLBACK
+window_enum(HWND hwnd, LPARAM lParam)
{
char buf[7] = {0};
PROCESS_HANDLE_ID p = *((PROCESS_HANDLE_ID*) (lParam));
DWORD pid = 0;
DWORD tid = 0;
+ /* we want to find and close any window that:
+ 1. is visible and
+ 2. is a dialog and
+ 3. is displayed by any of our child processes */
if (!IsWindowVisible(hwnd))
return TRUE;
- if (!GetClassNameA(hwnd, buf, 7))
+ if (!GetClassNameA(hwnd, buf, sizeof(buf)))
return TRUE; /* failed to read class name; presume it's not a dialog */
-
- if (strcmp(buf, "#32770"))
+
+ if (strcmp(buf, "#32770") != 0)
return TRUE; /* not a dialog */
+ /* GetWindowThreadProcessId returns 0 on error, otherwise thread id
+ of window message pump thread */
tid = GetWindowThreadProcessId(hwnd, &pid);
- if (tid && related(p.pid, pid))
+
+ if (tid && is_parent_child(p.pid, pid))
{
/* ask really nice */
PostMessageA(hwnd, WM_CLOSE, 0, 0);
@@ -1089,22 +1127,22 @@
if (WaitForSingleObject(p.h, 200) == WAIT_TIMEOUT)
{
PostThreadMessageA(tid, WM_QUIT, 0, 0);
- if (WaitForSingleObject(p.h, 500) == WAIT_TIMEOUT)
- {
- PostThreadMessageA(tid, WM_QUIT, 0, 0);
- WaitForSingleObject(p.h, 500);
- }
+ WaitForSingleObject(p.h, 300);
}
+
+ /* done, we do not want to check any other window now */
return FALSE;
}
return TRUE;
}
-void close_alert(HANDLE process)
+static void
+close_alert(HANDLE process)
{
DWORD pid = get_process_id(process);
- /* If process already exited or we just cannot get its process id, do not
go any further */
+ /* If process already exited or we just cannot get its process id, do not
+ go any further */
if (pid)
{
PROCESS_HANDLE_ID p = {process, pid};
@@ -1160,7 +1198,8 @@
{
double t = running_time(active_handles[i]);
- /* periodically (each 5 secs) review and close alert
dialogs hanging around */
+ /* periodically (each 5 secs) check and close message boxes
+ displayed by any of our child processes */
if ((alert_wait % ((unsigned int) 5)) == 0)
close_alert(active_handles[i]);
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Boost-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/boost-cvs