[comp.lang.eiffel] Garbage Collection Problem

dave@alfrat.uucp (Dave Cullen) (09/27/90)

I have been having problems with Segmentation errors being
created when turning on the automatic garbage collection
in Eiffel 2.2, using the option in the SDF. I used garbage
collection in Eiffel 2.1 without any problems, but since
the occurence of the bug seems to be program size dependent
this may have been luck.

So far I have traced the segmentation error to the function
"set_black" in "_gac.c". It occurs on the second of the following
two lines:

	_rt_3A7 = c_field ((int32)i, _rt_3Ao);
	if (!EXPANDED(_rt_3A7)) {
	...

The object pointed at by "_rt_3Ao" is a STRING and in memory looks
as follows:

	0xc0000002
	0x41f49c
	0xc1000035
	0x41f220

After the call to "c_field", "_rt_3A7" is set to 0xc1000035. Whilst
this should theoretically be an object pointer to the area of memory
used for the actual string, it looks rather more like the "info"
part of an object. In my system this looks like the start of a
LINKED_LIST object.

Questions:
(1) - Has anyone seen anything like this happen before?
(2) - Is it possible that the garbage collector allowed
      the reuse of some memory that wasn't completely dead, i.e.
      overwriting part of my STRING object.

This problem is quite urgent so if you've already solved it
or have any ideas about how to isolate it, I'd be most grateful.
Thanks,

Dave Cullen            | Tel. 02102-850514
A&F System Entwicklung | Email: dave@alfrat.uucp
4030 Ratingen          | Maybe: ...!unido!alfrat.uucp!dave
W. Germany             | Meine Beutelmaus hat verstopfung!

rick@tetrauk.UUCP (Rick Jones) (09/27/90)

In article <124@alfrat.uucp> dave@alfrat.uucp (Dave Cullen) writes:
>I have been having problems with Segmentation errors being
>created when turning on the automatic garbage collection
>in Eiffel 2.2, using the option in the SDF. I used garbage
>collection in Eiffel 2.1 without any problems, but since
>the occurence of the bug seems to be program size dependent
>this may have been luck.
>
>So far I have traced the segmentation error to the function
>"set_black" in "_gac.c". It occurs on the second of the following
>two lines:
>
>	_rt_3A7 = c_field ((int32)i, _rt_3Ao);
>	if (!EXPANDED(_rt_3A7)) {
>	...

There are definitely some bugs in garbage collection in 2.2, in general they
seem to result from the extra complications of dealing with expanded and
bitfield types (good news - 2.3 beta appears to have sorted a lot of it out).

One particular problem which may occur is also due to expanded types, and only
indirectly involves the garbage collector, despite the fact that that is where
it crashes!  This problem is quite specific, and occurs if you call the Create
routine on a class which contains an expanded object, and where any of the
actual arguments to Create are themselves function calls on other objects.

An example I found was creating a FILE object (this contains a DOUBLE, which is
an expanded type), where the argument - the file name - was generated by a
function call.  E.g.

	f: FILE ;
	f.Create (obj.getname) ;

"getname" is a function call on "obj" which returns a string, and does various
things before returning.  This may cause a random crash.  The reason is that
the "f" object is first allocated on the heap, and initialised with all 0's.
Then the "f.Create" is called, but of course "obj.getname" has to be called
first in order to provide the argument.  If the code in "getname" does anything
non-trivial, it will trigger a phase of garbage collection, which may result in
the collector looking at the newly-allocated null "f" object (with me so far?:)
But if "f" contains an expanded type, all-null values is not valid:  it should
have the header words of the expanded object embedded.  The creation of the
internal expanded objects is only done within the Create routine, when it calls
a hidden class-specific "expand" function.  There is thus a window where a new
object containing one or more expanded objects is in an invalid state.  If the
garbage collector gets to look at this object during this window period, it
finds what should be an expanded object with no header and just gets lost.

The only current solution is to change the source:

	f: FILE ;
	n: STRING ;
	n := obj.getname ;
	f.Create (n) ;

The real overhead of this is virtually zero, just slightly less succinct code.
This problem does not appear to be resolved in 2.3 (not beta anyway).

I can't tell from your description if this really is the problem, but I suggest
checking your source for these sort of things.  If it's not this, you may like
to know that I also re-worked the 2.2 garbage collector in several places,
mainly to see how much faster it would go, but also managed to fix some of the
other problems.  If you would like a copy, please email me.
(caveat: no guarantees or support!)

-- 
Rick Jones			The definition of atomic:
Tetra Ltd.				from the Greek meaning "indivisible"
Maidenhead, Berks, UK		So what is:
rick@tetrauk.uucp			an atomic explosion?

jp@eiffel.UUCP (Jean-Pierre Sarkis) (09/29/90)

In article <124@alfrat.uucp>, dave@alfrat.uucp (Dave Cullen) writes:
>I have been having problems with Segmentation errors being
>created when turning on the automatic garbage collection
>in Eiffel 2.2, using the option in the SDF. I used garbage
>collection in Eiffel 2.1 without any problems, but since
>the occurence of the bug seems to be program size dependent
>this may have been luck.
>
>  [ ... stuff deleted ... ]
>
>(1) - Has anyone seen anything like this happen before?
>(2) - Is it possible that the garbage collector allowed
>      the reuse of some memory that wasn't completely dead, i.e.
>      overwriting part of my STRING object.

 (1): Yes, we did !
 (2): No. But some new features added in 2.2B have forced
 us to rewrite some parts of the Garbage Collector and unfortunately
 introduce bugs in the code.

>This problem is quite urgent so if you've already solved it
>or have any ideas about how to isolate it, I'd be most grateful.
>Thanks

	Included at the end of this articles is a patch to partially fix
	the garbage collector as delivered by ISE in Eiffel 2.2B.

The patch mainly fixes the bug reported by Rick Jones in <742@tetrauk.UUCP>:
>
>  [ ... stuff deleted ... ]
>
>One particular problem which may occur is also due to expanded types, and only
>indirectly involves the garbage collector, despite the fact that that is where
>it crashes!  This problem is quite specific, and occurs if you call the Create
>routine on a class which contains an expanded object, and where any of the
>actual arguments to Create are themselves function calls on other objects.
>
>  [ ... stuff deleted ... ]
>
>This problem does not appear to be resolved in 2.3 (not beta anyway).

	This problem has been fixed in release 2.3, scheduled for
	release the end of October.

	The idea is to prevent the expanded attribute from being marked
	by the GC when the object containing it has not completely initialized.
	For those who report that they are not using any expanded attributes
	in their application; ANY is a client of STD_FILES which is a client
	of FILE. FILE has a DOUBLE attribute and DOUBLE is an expanded type.
	Thus, any Eiffel application using input/output facilities has an
	expanded object at run-time. :-)


*******************************************************************
		PATCH for EIFFEL 2.2B GARBAGE COLLECTOR

1) DO a BACKUP of the directory $INSTALLATION/Eiffel/files

2) Apply the following diffs on the file $INSTALLATION/Eiffel/files/_gac.c
------------------------ DIFF START -----------------------------
diff _gac.c.old _gac.c.patched:
279c279
<                   	(((int32)_rt_3A7 + (int32)c_fd_nb(_rt_3A7) + _rt_40a )
---
>                   	(((int32)_rt_3A7 + _rt_40d*((int32)c_fd_nb(_rt_3A7) + _rt_40a))
300c300
<          n = set_black (_rt_3A7, n);
---
>          if (_rt_3A7->nobj) n = set_black (_rt_3A7, n);
446c446
<                   	(((int32)_rt_3A7 + (int32)c_fd_nb(_rt_3A7) + _rt_40a )
---
>                   	(((int32)_rt_3A7 + _rt_40d*((int32)c_fd_nb(_rt_3A7) + _rt_40a))
467c467
<          _rt_3Al (_rt_3A7);
---
>          if (_rt_3A7->nobj) _rt_3Al (_rt_3A7);
------------------------ DIFF END -----------------------------

3) Save the file and generate the new run_time archive:

(Check the CFLAGS in makefile _makeD:
		`-O -DBSD' or `-O -DSYSTEMV' depending on your Unix system)

   execute:
			make -f _makeD

4) Recompile your application with the GARBAGE COLLECTOR turned ON
*******************************************************************


Hope this will help,


Jean-Pierre SARKIS
jp@eiffel.com
(Technical support: eiffel@eiffel.com)
-- 
Jean-Pierre SARKIS
Interactive Software Engineering

Reply-to: eiffel@eiffel.com