Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

PeekMessage causing freeze

davidgraham
Beginner
2,558 Views

I am using PeekMessage to get a keyboard input.

On my computer this works fine but on some computers and with Windows10 it is causing a freeze and the user has to do 'Ctrl Alt Delete'.

I feel as if some resource or memory is getting filled. I have include the code below. I removed the ClipCursor call in case it was causing the problem.

Can you suggest what the problem could be.

Thanks 

        SUBROUTINE GETCHA (K)
!       ----------------------------------------------------------------
!       GET KEYPRESS RETURN WITH VALUE IN K

  use grad_inc

  include 'cgipar.gcb' ! FKEY
        
  type (T_MSG) msg
  
  integer*2 i,iext,k
  integer(bool)   bRet
  logical*4   lret
  

  !!lret=ClipCursor (rectmain) ! to keep cursor within drawing area to stop selecting other option

   10 bRet=PeekMessage (msg,hWndMain,WM_LBUTTONUP,WM_RBUTTONUP,PM_REMOVE) ! LRbutton getcha
  if (bret==1) then
      ! valid message
   if (msg%message==WM_LBUTTONUP) then
    k=32 ! space
    goto 90
   elseif (msg%message==WM_RBUTTONUP) then
    k=184 ! f9
    goto 90
   endif
  endif
!  next function changed from getmessage to peekmessage 22 Dec
  bret=PeekMessage (msg,hWndMain,WM_KEYDOWN,WM_KEYDOWN,PM_REMOVE) ! keydown getcha
  if (bret==1) then
      ! valid message
   k=127
   i=msg%wParam                ! virtual key code
   iext=btest(msg%lParam,24)   ! extended key flag
   if (iext==-1) then  ! changed from if (iext==1) then
    ! arrow key
    if (i==37) then         ! left arrow    VK_LEFT 0025
     k=-76
    elseif (i==38) then     ! up arrow      VK_UP 0026
     k=-85
    elseif (i==39) then     ! right arrow   VK_RIGHT 0027
     k=-82
    elseif (i==40) then     ! down arrow    VK_DOWN 0028
     k=-68
    else
     k=-i
    endif
   else
    if (i>=112.AND.i<=123) then     ! function keys VK_F1 0077 to VK_F12 007B
     k=fkey(i-111) 
    elseif (i>=44.AND.i<=90) then   ! normal keys including 0-9 & A-Z
     k=i
    elseif (i<33) then              ! special keys
     k=i
    elseif (i>=96.AND.i<=105) then  ! numeric keypad  
     k=i-48
    elseif (i>=106.AND.i<=111) then ! maths keys
     k=i-64
    elseif (i>187) then             ! special keys
     k=i-144
    else
     k=i
    endif
    if (k==27) k=184 ! Esc = f9 abort 1/11/02 David Graham
   endif
  else
   ! no messagaes
   k=0
   goto 10
  endif

90      continue
        !!lret=ClipCursor (NULL)
  return
  end subroutine

 

0 Kudos
12 Replies
Stephen_Sutcliffe1
2,558 Views

I had this issue when the OS changed from XP to Vista/Windows 7 etc.

My fix was to call the API function DisableProcessWindowsGhosting

using the following interface:

interface

!DEC$ IF DEFINED(_X86_)

subroutine DisableProcessWindowsGhosting()

!DEC$ ATTRIBUTES DEFAULT , STDCALL, DECORATE, ALIAS: 'DisableProcessWindowsGhosting' :: DisableProcessWindowsGhosting

!DEC$ ELSE

subroutine DisableProcessWindowsGhosting() BIND(C,NAME='DisableProcessWindowsGhosting')

!DEC$ ENDIF

end subroutine

end interface

Good luck

 

0 Kudos
davidgraham
Beginner
2,558 Views

Thanks, that appears to have fixed it.

 

0 Kudos
Steven_L_Intel1
Employee
2,558 Views

The interface can be simplified as of ifort version 16 to:

interface
subroutine DisableProcessGhosting () bind(C,name="DisableProcessGhosting")
!DEC$ ATTRIBUTES STDCALL :: DisableProcessGhosting
end subroutine DisableProcessGhosting
end interface

Even in past releases, you could use what was in the _X86_ case without the conditional.

The interface for this routine has been added to module USER32 for the 17.0 release, which means that you will get compile errors if you use that module and redefine the interface. 

0 Kudos
davidgraham
Beginner
2,558 Views

This problem is still occurring erratically.

I added the DisableProcessGhosting and that helped but I'm still getting cases where the software freezes when its waiting for input from the user.

When I try to reproduce the problem I can't then it occurs later. I feel something is getting 'filled up'.

Do you have any advice on how to track down this sort of problem?

Thanks

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,558 Views

You might find this (https://msdn.microsoft.com/en-us/library/windows/desktop/dd744765(v=vs.85).aspx) of interest. Look at the Best Practices section.

Jim Dempsey

0 Kudos
IanH
Honored Contributor II
2,558 Views

I would be very suspicious of any design that used PeekMessage.  Chances are that you are leaving (or not responding correctly to) messages in the message queue for the thread
 

0 Kudos
davidgraham
Beginner
2,558 Views

Thanks for your comments.

Jim,

The example shows a long process taking place and the user presses a key an there is no response.

In my case the program is doing 'nothing' it is just waiting for a user input.

Ian,

What would you recommend instead of PeekMessage - do you have a small example?

------------

I have added bret=PeekMessage (msg,NULL,0,0,PM_NOREMOVE) which I had added previously in other locations to help.

The problem is that it is very difficult to recreate the problem, it occasionally happens when the program is waiting for the user to press a key, then having to do Control Alt Delete after it hangs is very annoying. I have made the change above and try it with a few users.          

0 Kudos
jimdempseyatthecove
Honored Contributor III
2,558 Views

Would clicking on a window control get you out of the deadlock? (e.d. minimize, max/sizable, X)

If not, then use the debugger to attach to the process, then pause into it. Hopefully you can discover the deadlock. What may be happening is  Windows is hibernating the process when not active (to conserve power). This is typically done on phones or tablets. Maybe this is what they mean by Ghosting.

Hack (possible), insert alongside your PeekMessage a periodic PokeMessage (you figure out the name) that creates an artificial even into your message handler. You can discard the heartbeat message.  The idea is to keep the process alive (not hibernate).

Jim Dempsey

0 Kudos
garylscott1
Beginner
2,558 Views

In the process of "ghosting", windows hides the "real" window and replaces it with a bitmap copy.  (and adds "not responding").  There is no active application control or button to click on when in this state.  Clicking on the bitmap will usually bring up some sort of "do you want to terminate" dialog.  However, this ghosting state is not a permanent condition.  If the loop or process causing the hang eventually resolves, control will be restored to the application.  In theory calling peekmessage once each 4.9 seconds should be enough to prevent a "not responding"/ghosting message from occurring, but of course it does not resolve any process hang condition itself.  Turning off ghosting in that case will be irrelevant.

0 Kudos
IanH
Honored Contributor II
2,558 Views

davidgraham wrote:
What would you recommend instead of PeekMessage - do you have a small example?

I would expect all initial mesage retrieval to be done using the typical message loop for the thread.  PeekMesage should only be for very specialised stuff. 

0 Kudos
davidgraham
Beginner
2,558 Views

Thanks for the suggestions. It occasionally hangs after about 10 seconds so it won't have gone into hibernation. I'm not sure if I have fixed it as it's intermittent. 

0 Kudos
John_Paul_Chacha
Beginner
2,558 Views

The PeekMessage() function has two annoying "features": 

(1) It doesn't retrieve messages in the order they were posted, but rather in a predefined order based on the type of message, and,  

(2) If any window refuses to process any WM_PAINT message, it will repeatedly replay that exact message ad infinitum until it gets processed (which may never happen).

These two features act in concert to create interesting single-thread deadlock situations. Ask me how I know. 

0 Kudos
Reply