注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

写着玩

Bob

 
 
 

日志

 
 
 
 

防假死一周研究报告  

2009-11-25 22:17:20|  分类: Win32 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

目前我所知的,能防假死的浏览器有:Chrome,Maxthon,Theworld,搜狗.除了Chrome外,其余的都是IE内核,它们的实现方式都是一样的,页面窗口与主程序窗口分离,每个页面一个线程.事实上,除了Chrome能完美实现防假死,其余都有瑕疵.

 

瑕疵有3

点击主窗口的时候,发现页面失去了输入焦点
按alt+tab键切换窗口的时候,发现第一次不能成功,按两次才行
弹出的模态窗口并不模态,主窗口仍能动,其他页面也能动
造成这些瑕疵,还是因为页面窗口与主程序窗口分离,问题是为什么不能在同一个窗口呢?实验证明,放在同一个窗口,即使是不同进程,子窗口处于假死状态的话,主窗口也同样假死了.

这一周,我一直在尝试一个事情,子窗口假死的时候,主窗口能否不死,两个窗口是处于不同线程.

测试内容如下:有窗口A和窗口B,A是由主线程创建,然后创建一个线程,再这个线程上创建B,CreateWindow的hWndParent参数是A的hwnd.显然A,B都有各自的消息循环,但当B执行一个死循环的时候,A也死掉,没有反应了,但如果B的hWndParent是NULL的话,当B无响应时,A仍然能活动自如.于是猜测是当两个窗口处于父子关系时,它们的消息循环是否合并了?

但,后来翻遍了资料,都没有讲两个不同线程的子父窗口的消息循环是怎样的.

最后发现在B执行死循环操作的时候,如果添加PeekMessage函数,那么A是可以正常响应的.PeekMessage是什么?就是在消息队列中把消息提出来,可以把消息清除,也可以不清除(使用PM_REMOVE 或 PM_NOREMOVE)标记.但如果不清除,A仍然是不能响应.于是可以猜测,当这两个窗口处于父子关系的时候,主进程会先将它们的消息放在同一队列中,然后再分发给各自的线程,所以当B堵塞的时候,A就无法响应,只有将属于B的消息都清除掉,A的消息才能到达A.

确实是这样吗?找不到资料,不能确定.

如果猜测是正确的,那么就要想办法将B的消息从消息队列中清除掉,而这个操作只能在另一个线程中,但PeekMessage做的只是当前线程的,也没有别的函数可以做到.

看来,目前来说,实验结果是不成功.

其实也是,Maxthon,Theworld,搜狗都不是省油的灯,他们肯定也想过,不得已才采用这个"分离"的办法.但为何Chrome能做到?不要忘了,那可是google的孩子,另外Chrome采用的是开源的核心,在处理这个事情上更方便.

最后附上测试代码,很混乱,见谅.

// MyWin.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "resource.h"
#include <windows.h>
#define  szClassMain "MainWClass"
#define  szClassChild "ChildWClass"

// Global variable
 
HINSTANCE hinst;
HWND hParent;
HWND hChild,hChild2;
HANDLE hTh1;
DWORD hThID1;
HHOOK hMsgHook;

// Function prototypes.
 
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
InitApplication(HINSTANCE);
InitInstance(HINSTANCE, int);
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM);
BOOL WINAPI ThreadProc(HWND);
BOOL WINAPI ThreadProc2(HWND);
LRESULT CALLBACK GetMsgProc(int,WPARAM ,LPARAM );

// Application entry point.
 
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
 hinst=hinstance;

    if (!InitApplication(hinstance))
        return FALSE;
 
    if (!InitInstance(hinstance, nCmdShow))
        return FALSE;
 
 DWORD thid;
 hTh1=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,hParent,0,&thid);
 hThID1=thid;
 HANDLE hTh2=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc2,hParent,0,&thid);

    while (int sc=GetMessage(&msg, (HWND) NULL, 0, 0) != 0 && sc != -1)
    {  
  if(!SendMessageTimeout(hChild,WM_USER+100,0,0,0,200,NULL))
   MessageBox(0,"fat","fat",MB_OK);
  TranslateMessage(&msg);
  DispatchMessage(&msg);  
    }
    return msg.wParam;
        UNREFERENCED_PARAMETER(lpCmdLine);
}
 
BOOL InitApplication(HINSTANCE hinstance)
{
    WNDCLASSEX wcx;
 
    // Fill in the window class structure with parameters
    // that describe the main window.
 
    wcx.cbSize = sizeof(WNDCLASSEX);          // size of structure
    wcx.style = CS_HREDRAW | CS_VREDRAW;// redraw if size changes
    wcx.lpfnWndProc = (WNDPROC)MainWndProc;     // points to window procedure
    wcx.cbClsExtra = 0;                // no extra class memory
    wcx.cbWndExtra = 0;                // no extra window memory
    wcx.hInstance = hinstance;         // handle to instance
    wcx.hIcon =NULL;// LoadIcon(NULL,
        //IDI_APPLICATION);              // predefined app. icon
    wcx.hCursor = NULL;                    // predefined arrow
    wcx.hbrBackground = (HBRUSH)COLOR_WINDOW;                  // white background brush
    wcx.lpszMenuName =  NULL;//"MainMenu";    // name of menu resource
    wcx.lpszClassName = szClassMain;  // name of window class
    wcx.hIconSm = NULL;
 
    // Register the window class.
 
    RegisterClassEx(&wcx);
 
 wcx.lpfnWndProc = (WNDPROC)ChildWndProc;     // points to window procedure
 wcx.lpszClassName = szClassChild;
 wcx.lpszMenuName=(LPCSTR)IDR_MENU1;
 return RegisterClassEx(&wcx);

}
 
BOOL InitInstance(HINSTANCE hinstance, int nCmdShow)
{
    HWND hwnd;
 
    // Save the application-instance handle.
 
    //hinst = hinstance;
 
    // Create the main window.
 
    hwnd = CreateWindow(
        "MainWClass",        // name of window class
        "Sample",            // title-bar string
        WS_OVERLAPPEDWINDOW , // top-level window
        CW_USEDEFAULT,       // default horizontal position
        CW_USEDEFAULT,       // default vertical position
        400,       // default width
        300,       // default height
        (HWND) NULL,         // no owner window
        (HMENU) NULL,        // use class menu
        hinstance,           // handle to application instance
        (LPVOID) NULL);      // no window-creation data
 hParent=hwnd;
    if (!hwnd)
        return FALSE;
 
    // Show the window and send a WM_PAINT message to the window
    // procedure.
 
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
 

    return TRUE;
 
}


LRESULT CALLBACK MainWndProc(
    HWND hwnd,        // handle to window
    UINT uMsg,        // message identifier
    WPARAM wParam,    // first message parameter
    LPARAM lParam)    // second message parameter
{
 
    switch (uMsg)
    { 
 
        case WM_DESTROY:
            // Clean up window-specific data objects.
   PostQuitMessage(0);
            break;
        //
        // Process other messages.
        //
 
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}


LRESULT CALLBACK ChildWndProc(
    HWND hwnd,        // handle to window
    UINT uMsg,        // message identifier
    WPARAM wParam,    // first message parameter
    LPARAM lParam)    // second message parameter
{
 
 BOOL fDone=false;
 MSG msg;

    switch (uMsg)
    { 
 case WM_COMMAND: 
   if(hwnd==hChild)
   {
    if(wParam==IDM_Test)
    while(!fDone)
    {
     //while (PeekMessage(&msg, hwnd,  0, 0, PM_REMOVE))
     //{
      /*switch(msg.message)
      {
      case WM_KEYDOWN:
       fDone=true;
      }*/
     //}
    }
   }
   else if(hwnd==hChild2)
   {
    switch(wParam)
    {
    case IDM_Test:
     SuspendThread(hTh1);
     break;
    //hMsgHook=SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,0,hThID1);
    /*if(SendMessageTimeout(hChild,WM_USER+100,0,0,0,1000,NULL))
     MessageBox(0,"sus","sus",MB_OK);
    else
    {
     MessageBox(0,"fat","fat",MB_OK);
     if(SuspendThread(hTh1))MessageBox(0,"s s","ss",MB_OK);
    }*/
    case IDM_Resume:
     ResumeThread(hTh1);
     break;
    }
   }
 
  break;
 
        case WM_DESTROY:
            // Clean up window-specific data objects.
   PostQuitMessage(0);
            break;
        //
        // Process other messages.
        //
 
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}


BOOL WINAPI ThreadProc(HWND hParent)
{
 HWND hwnd;
 
       
 hwnd = CreateWindow(
        szClassChild,        // name of window class
        "Child",            // title-bar string
        WS_OVERLAPPEDWINDOW , // top-level window
        CW_USEDEFAULT,       // default horizontal position
        CW_USEDEFAULT,       // default vertical position
        400,       // default width
        300,       // default height
        (HWND) hParent,         // no owner window
        (HMENU) NULL,        // use class menu
        hinst,           // handle to application instance
        (LPVOID) NULL);      // no window-creation data

 hChild=hwnd;

    if (!hwnd)
        return FALSE;
 
    // Show the window and send a WM_PAINT message to the window
    // procedure.
 
    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);
 
 MSG msg;
 while (int sc=GetMessage(&msg, (HWND) NULL, 0, 0) != 0 && sc != -1)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return TRUE;
}

BOOL WINAPI ThreadProc2(HWND hParent)
{
 HWND hwnd;
 
       
 hwnd = CreateWindow(
        szClassChild,        // name of window class
        "Child2",            // title-bar string
        WS_OVERLAPPEDWINDOW , // top-level window
        CW_USEDEFAULT,       // default horizontal position
        CW_USEDEFAULT,       // default vertical position
        400,       // default width
        300,       // default height
        (HWND) NULL,         // no owner window
        (HMENU) NULL,        // use class menu
        hinst,           // handle to application instance
        (LPVOID) NULL);      // no window-creation data

 hChild2=hwnd;

    if (!hwnd)
        return FALSE;
 
    // Show the window and send a WM_PAINT message to the window
    // procedure.
 
    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);
 
 MSG msg;
 while (int sc=GetMessage(&msg, (HWND) NULL, 0, 0) != 0 && sc != -1)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return TRUE;
}


LRESULT CALLBACK GetMsgProc(
  int code,       // hook code
  WPARAM wParam,  // removal option
  LPARAM lParam   // message
)
{
 MSG *msg=(MSG *)lParam;
 if(msg->message==WM_KEYDOWN)
 {
  int i=1;
 }
 return CallNextHookEx(hMsgHook,code,wParam,lParam);
}

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lingll/archive/2009/03/16/3993392.aspx

  评论这张
 
阅读(156)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017