Tom Lane wrote:
> Alvaro Herrera <alvhe...@commandprompt.com> writes:
> > Some time ago I noticed that in postmaster.c there's a corner case which
> > probably causes postmaster to exit in out-of-memory condition.  See
> > BackendStartup, near the bottom, there's a call to DLNewElem().  The
> > problem is that this function calls palloc() and thus can elog(ERROR) on
> > OOM, but postmaster has no way to defend itself from this and would die.
> 
> So?  There are probably hundreds of palloc calls that are reachable from
> the postmaster main loop.  If this were allocating more than a few bytes
> of memory, it might be worth worrying about.

Hundreds?  I think you'd be hard pressed to find as much as a dozen :-)
I mean stuff that's called inside ServerLoop, of course.  There are a
few places calling alloc-type functions, but as far as I see they use
calloc or malloc, and behave "sanely" (i.e. not elog(ERROR)) in OOM.

Note that BackendStartup itself is very careful about allocating a
Backend struct, even when it's just ~10 bytes on 32 bits machines.

I think a patch to solve this is as simple as the attached.

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.
Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/postmaster/postmaster.c,v
retrieving revision 1.551.2.1
diff -c -p -r1.551.2.1 postmaster.c
*** src/backend/postmaster/postmaster.c	27 Jun 2008 01:53:31 -0000	1.551.2.1
--- src/backend/postmaster/postmaster.c	6 Apr 2009 23:14:00 -0000
*************** BackendStartup(Port *port)
*** 2774,2779 ****
--- 2774,2780 ----
  {
  	Backend    *bn;				/* for backend cleanup */
  	pid_t		pid;
+ 	Dlelem	   *newel;
  
  	/*
  	 * Compute the cancel key that will be assigned to this backend. The
*************** BackendStartup(Port *port)
*** 2794,2799 ****
--- 2795,2818 ----
  				 errmsg("out of memory")));
  		return STATUS_ERROR;
  	}
+ 	PG_TRY();
+ 	{
+ 		newel = DLNewElem(bn);
+ 		elog(ERROR, "out of luck :-(");
+ 	}
+ 	PG_CATCH();
+ 	{
+ 		/*
+ 		 * it would be great if we could just reduce the error severity of the
+ 		 * current error
+ 		 */
+ 		FlushErrorState();
+ 		ereport(LOG,
+ 				(errcode(ERRCODE_OUT_OF_MEMORY),
+ 				 errmsg("out of memory")));
+ 		return STATUS_ERROR;
+ 	}
+ 	PG_END_TRY();
  
  	/* Pass down canAcceptConnections state (kluge for EXEC_BACKEND case) */
  	port->canAcceptConnections = canAcceptConnections();
*************** BackendStartup(Port *port)
*** 2857,2863 ****
  	bn->cancel_key = MyCancelKey;
  	bn->is_autovacuum = false;
  	bn->dead_end = (port->canAcceptConnections != CAC_OK);
! 	DLAddHead(BackendList, DLNewElem(bn));
  #ifdef EXEC_BACKEND
  	if (!bn->dead_end)
  		ShmemBackendArrayAdd(bn);
--- 2876,2883 ----
  	bn->cancel_key = MyCancelKey;
  	bn->is_autovacuum = false;
  	bn->dead_end = (port->canAcceptConnections != CAC_OK);
! 
! 	DLAddHead(BackendList, newel);
  #ifdef EXEC_BACKEND
  	if (!bn->dead_end)
  		ShmemBackendArrayAdd(bn);
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to