PR# 13413 bad behavior when opening and closing EV_NOTIFY_DIALOG

Problem Report Summary
Submitter: darppp
Category: .NET
Priority: High
Date: 2007/09/20
Class: Bug
Severity: Critical
Number: 13413
Release: 6.0.6.9367
Confidential: No
Status: Closed
Responsible: ted_eiffel
Environment: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.2; WOW64; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; InfoPath.2; .NET CLR 1.1.4322)
Synopsis: bad behavior when opening and closing EV_NOTIFY_DIALOG

Description
I'm having various crashes with fairly simple code under Eiffel.NET. Bellow is the code that I use for testing. I press a button, open a EV_INFORMATION_DIALOG, close the dialog and then press the button again. After several iterations one of several things happen:

- The dialog doesn't draw completelly. A button may be missing or positioned at the wrong place
- GetLastError with code 1406 shows up
- Exception that indicates write into a protected memory and that memory may have been corrupted.

The EiffelStudio version is 6.0.6.9367. Interestingly enough when I try with EV_COLOR_DIALOG instead of EV_INFORMATION_DIALOG the problems go away. Julian mentioned that it uses different implementation. I tried also with an agent opening EV_TITLED_WINDOWs and after 6-7 windows opened I usually get GetLastError with 1406.
You can give me a call and shadow me if you have trouble reproducing the problem
Thanks,
Darin
925-253-3472



                e: EV_TITLED_WINDOW
                a: EV_APPLICATION
                b: EV_BUTTON
                d: EV_INFORMATION_DIALOG

                make is
                                                -- Creation procedure.
                                local
                                do
                                                create a
                                                create e
                                                create b.make_with_text_and_action ("Do It", agent doit)
                                                e.extend (b)
                                                e.show
                                                a.launch
                                end

                doit is
                                                --
                                local
                                do
                                                create d
                                                d.show_modal_to_window (e)
                                end

To Reproduce
use the code from the description
Problem Report Interactions
From:manus_eiffel    Date:2008/08/21    Status: Closed    Download   
It should now be fixed with a slightly different fix (see rev#74532).

From:ted_eiffel    Date:2008/08/21    Download   
No, I don't get the precondition violation.

From:manus_eiffel    Date:2008/08/21    Download   
It is about the same problem. Are you getting the precondition violation in `eif_id_object' in?

From:ted_eiffel    Date:2008/08/20    Status: Analyzed    Download   
I cannot reproduce with the code posted originally. However, I can still get something similar with either of the following `doit':
	doit is
		do
			create d
			d.show_relative_to_window (e)
		end
and
	doit is
		local
			ge: INTEGER
		do
			create d
			d.show_relative_to_window (e)
			{GC}.collect
		end

To reproduce, keep clicking "Do It". Do not close dialogs.

From:manus_eiffel    Date:2008/08/20    Download   
Fix is included in rev#74504.

From:manus_eiffel    Date:2008/08/20    Status: Closed    Download   
I think I found the problem. Can you replace `dispose' in WEL_WINDOW by the following:


	dispose is
			-- Free allocated memory.
		local
			l_null, l_data: POINTER
			l_object_id: INTEGER
		do
				-- Free memory taken by `internal_data'.
			l_data := internal_data
			if l_data /= l_null then
				l_object_id := {WEL_INTERNAL_DATA}.object_id (l_data)
				check
					l_object_id_valid: l_object_id > 0
				end
				eif_object_id_free (l_object_id)
					-- To mark that area as been freed
				{WEL_INTERNAL_DATA}.set_object_id (l_data, -1)
				if item /= l_null then
						-- The data is not usable anymore so we need to
						-- remove it from GWLP_USERDATA otherwise bad things
						-- might happen.
					cwin_set_window_long (item, gwlp_userdata, l_null)
				end
				l_data.memory_free
				internal_data := l_null
			end

			Precursor {WEL_ANY}
		end

Could you confirm it works?


From:manus_eiffel    Date:2008/08/20    Download   
One thing I just noticed is that if I run your code outside a debugger (be it VisualStudio or EiffelStudio) the program does not crash.

Can you confirm this too?

If this is the case, then it is clearly a Microsoft bugs. Debugging it when it failed showed that most likely there is either a problem with global variable or with WeakReference. It is hard for me to tell which one since although reproducible, it is always happening to a different object.

From:ted_eiffel    Date:2008/07/30    Download   
Maybe I am wrong. I looked at the runtime again, object put into `object_id_stack' can be collected. Now I don't know why windows on Windows are kept in such case, they should be collected too. (This happens on Linux)
Do you have any ideas?