Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Mar 2008 11:48:10 +0200
From:      Kostik Belousov <kostikbel@gmail.com>
To:        Tim Kientzle <kientzle@freebsd.org>
Cc:        Garrett Wollman <wollman@bimajority.org>, Jason Evans <jasone@freebsd.org>, Bruce Evans <brde@optusnet.com.au>, current@freebsd.org
Subject:   Re: Breaking the crt1.o -> atexit() -> malloc() dependency
Message-ID:  <20080306094810.GM57756@deviant.kiev.zoral.com.ua>
In-Reply-To: <47CF4500.2050509@freebsd.org>
References:  <200802280409.m1S498YJ062561@repoman.freebsd.org> <20080228231522.F57564@delplex.bde.org> <alpine.BSF.1.00.0802281109320.27124@thor.farley.org> <20080229141527.N59899@delplex.bde.org> <18375.43955.908262.696223@hergotha.csail.mit.edu> <47C8D0AB.20506@freebsd.org> <20080302062610.V66431@delplex.bde.org> <47CA2192.8020802@FreeBSD.org> <20080303065527.K69705@delplex.bde.org> <47CF4500.2050509@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--X95ZMRfl5Jak4ILv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Wed, Mar 05, 2008 at 05:12:32PM -0800, Tim Kientzle wrote:
> There was some recent discussion on the commit mailing
> list about how to disentangle crt1.o from malloc().
>=20
> Here's a design that I think addresses all of the
> issues people raised, including the POSIX requirement
> that atexit() always be able to support 32 registrations.
> It does it without using sbrk() or mmap(), either.
>=20
> The basic idea is to lift the malloc() call up into
> atexit() and have atexit_register() use statically-allocated
> storage if atexit() didn't provide dynamically-allocated
> storage.
>=20
> This basically changes atexit() to something like this pseudocode:
>=20
> int atexit(void (*function)(void))
> {
> 	struct atexit *storage =3D malloc(sizeof(struct atexit));
>=20
> 	/* Note: If malloc() fails, __atexit_register will try
> 	 * to statically allocate, so we don't check here
> 	 * for malloc() failure.  */
> 	return __atexit_register(function, storage);
> }
>=20
> Then atexit_register either uses the block that was provided
> or grabs an item from a static pool if there wasn't one:
>=20
> /* 32 required by POSIX plus a few for crt1.o */
> static struct atexit pool[40];
>=20
> int atexit_register(void (*function)(void), struct atexit *storage)
> {
> 	if (storage =3D=3D NULL) {
> 		storage =3D ... next item from static pool ...
> 	}
> 	storage.func =3D function;
> 	... add storage block to linked list ...
> }
>=20
> Avoiding free() from the low-level code is a little trickier
> but I think it can be done by having the low-level code
> put (dynamically-allocated) blocks back onto a free list
> and having the higher-level atexit() release that list
> on the next registration.  This should handle the case
> of a dynamic library being repeatedly loaded and unloaded.
> Of course, it's unnecessary to release the atexit storage
> on program exit.
>=20
> In particular, crt1.o can then call atexit_register(f, NULL)
> to register its exit functions without creating a dependency on
> malloc.
>=20
> This does require that atexit() and atexit_register() be in
> separate source files, but I think it addresses all of the other
> concerns people have raised.

I mostly agree with proposal, but there is also __cxa_atexit().

And, besides the issue of the size of the static linked executables,
there is more exposed problem of atexit() memory leaks. See
http://lists.freebsd.org/pipermail/freebsd-stable/2008-February/040644.html

--X95ZMRfl5Jak4ILv
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (FreeBSD)

iEYEARECAAYFAkfPvdoACgkQC3+MBN1Mb4ijfQCfWyElBIZX5aJ+ifTi2v0KrLCQ
mzkAoKtdALPkHgCPDmBqDh3tXDBH8N3O
=6o82
-----END PGP SIGNATURE-----

--X95ZMRfl5Jak4ILv--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20080306094810.GM57756>