[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

g++ 3.3 and inline / cc1plus gets killed



Hi,

during OOo's compilation the following is done:

ccache g++ -fmessage-length=0 -c -I. -I. -I../inc -I../../../inc -I../../../unx/inc -I../../../unxlngi4.pro/inc -I. -I/home/rene/Debian/Pakete/OpenOffice.org/Hauptpaket/openoffice.org-1.0.3/build-tree/oo_1.0.3_src/solver/641/unxlngi4.pro/inc/stl -I/home/rene/Debian/Pakete/OpenOffice.org/Hauptpaket/openoffice.org-1.0.3/build-tree/oo_1.0.3_src/solver/641/unxlngi4.pro/inc/external -I/home/rene/Debian/Pakete/OpenOffice.org/Hauptpaket/openoffice.org-1.0.3/build-tree/oo_1.0.3_src/solver/641/unxlngi4.pro/inc -I/home/rene/Debian/Pakete/OpenOffice.org/Hauptpaket/openoffice.org-1.0.3/build-tree/oo_1.0.3_src/solenv/unxlngi4/inc -I/home/rene/Debian/Pakete/OpenOffice.org/Hauptpaket/openoffice.org-1.0.3/build-tree/oo_1.0.3_src/solenv/inc -I/home/rene/Debian/Pakete/OpenOffice.org/Hauptpaket/openoffice.org-1.0.3/build-tree/oo_1.0.3_src/res -I/home/rene/Debian/Pakete/OpenOffice.org/Hauptpaket/openoffice.org-1.0.3/stlport-home/stlport -I/home/rene/Debian/Pakete/OpenOffice.org/Hauptpaket/openoffice.org-1.0.3/stlport-home/include/stlport -I/home/rene/Debian/Pakete/OpenOffice.org/Hauptpaket/openoffice.org-1.0.3/stlport-home/include/stlport -I/home/rene/Debian/Pakete/OpenOffice.org/Hauptpaket/openoffice.org-1.0.3/build-tree/oo_1.0.3_src/solenv/inc/Xp31 -I/usr/lib/j2se/1.3/include -I/usr/lib/j2se/1.3/include/linux -I/usr/lib/j2se/1.3/include/native_threads/include -I/usr/X11R6/include     -I. -I../../../res -I. -O   -pipe -mcpu=pentiumpro -fno-for-scope -fpermissive -fexceptions -fno-enforce-eh-specs   -fpic -DLINUX -DUNX -DVCL -DGCC -DC300 -DINTEL -DCVER=C300 -D_USE_NAMESPACE -DGLIBC=2 -DX86 -D_PTHREADS -D_REENTRANT -DNEW_SOLAR -D_USE_NAMESPACE=1 -DSTLPORT_VERSION=400 -D__DMAKE -DUNIX -DCPPU_ENV=gcc3 -DSUPD=641 -DBUILD=8584 -DPRODUCT -DNDEBUG -DPRODUCT_FULL -DEXCEPTIONS_ON -DCUI -DSOLAR_JAVA -DSRC641  -DSHAREDLIB -D_DLL_  -DMULTITHREAD  -w -o ../../../unxlngi4.pro/slo/urp_reader.o /home/rene/Debian/Pakete/OpenOffice.org/Hauptpaket/openoffice.org-1.0.3/build-tree/oo_1.0.3_src/bridges/source/remote/urp/urp_reader.cxx

This worked with g++ 3.2 but not with 3.3.

It constantly consumes all my mamor (512 MB RAM, 512 MB swap) till it
gets OOM-killed by the kernel.

As I asked on debian-devel, James answered me:

20:11 <          elmo > g++-3.3 has a silly inline default, IIRC, if you're
                        OOM-ing because of g++-3.3 with a large C++ source like
                        OOo, you could try lowering it
20:11 <          elmo > there was a thread about it on the gcc list; I'm
                        reasonably sure it didn't get resolved before 3.3 was
                        released

[...]

20:18 <          elmo > rene: see
                        http://gcc.gnu.org/ml/gcc/2003-05/msg00362.html and
                        other mails in that thread

OK, I tried with -finline-limit=x, x=4,3,2,1,0, compiled with -fno-inline,
with -O0 and I even removed 3 of the 4 inlines from the source. No effect.

It may be worth noting that the free "normal" memory during the "normal"
compilation is between 4-12M during compile anyhow...

I attach the source file here; a preprocessed source isn't available
because it is not generated :( (it seems that g++ fails during
preprocessing..)

What is the cause of that? Bug in g++? Should I report one "officially"?
Is there a workaround?

Regards,

Rene
/*************************************************************************
 *
 *  $RCSfile: urp_reader.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: jbu $ $Date: 2001/08/31 16:16:52 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include <string.h>

#include <osl/diagnose.h>
#include <rtl/ustrbuf.hxx>

#include <bridges/remote/connection.h>
#include <bridges/remote/counter.hxx>
#include <bridges/remote/context.h>
#include <bridges/remote/helper.hxx>

#include <uno/environment.h>

#include "urp_reader.hxx"
#include "urp_writer.hxx"
#include "urp_dispatch.hxx"
#include "urp_job.hxx"
#include "urp_bridgeimpl.hxx"
#include "urp_log.hxx"
#include "urp_propertyobject.hxx"

using namespace ::rtl;
using namespace ::osl;
using namespace ::com::sun::star::uno;

#ifdef DEBUG
static MyCounter thisCounter( "DEBUG : ReaderThread" );
#endif

namespace bridges_urp
{

	/**
	 * This callback is used to ensure, that the release call is sent for the correct type.
	 *
	 ***/
	void SAL_CALL urp_releaseRemoteCallback (
		remote_Interface *pRemoteI,rtl_uString *pOid,
		typelib_TypeDescriptionReference *pTypeRef,
		uno_Environment *pEnvRemote	)
	{
		remote_Context *pContext = (remote_Context *) pEnvRemote->pContext;
		urp_BridgeImpl *pImpl = (urp_BridgeImpl*) ( pContext->m_pBridgeImpl );

		pImpl->m_pWriter->insertReleaseRemoteCall( pOid , pTypeRef );
	}


	struct MessageFlags
	{
		sal_uInt16 nMethodId;
		sal_Bool bRequest;
		sal_Bool bType;
		sal_Bool bOid;
		sal_Bool bTid;
		sal_Bool bException;
		sal_Bool bMustReply;
 		sal_Bool bSynchronous;
		sal_Bool bMoreFlags;
		sal_Bool bIgnoreCache;
		sal_Bool bBridgePropertyCall;
		///--------------------------
		inline MessageFlags()
			{
				bTid = sal_False;
				bOid = sal_False;
				bType = sal_False;
				bException = sal_False;
				bMoreFlags = sal_False;
				bIgnoreCache = sal_False;
				bBridgePropertyCall = sal_False;
			}
		//---------------------------
	}; // end struct MessageFlags
	

inline sal_Bool OReaderThread::getMemberTypeDescription(
	typelib_InterfaceAttributeTypeDescription **ppAttributeType,
	typelib_InterfaceMethodTypeDescription **ppMethodType,
	sal_Bool *pbIsSetter,
	sal_uInt16 nMethodId ,
	typelib_TypeDescriptionReference * pITypeRef )
{
	if( pITypeRef->eTypeClass != typelib_TypeClass_INTERFACE )
	{
		OUString sMessage( RTL_CONSTASCII_USTRINGPARAM( "interface type is not of typeclass interface (" ));
		sMessage += OUString::valueOf( (sal_Int32) pITypeRef->eTypeClass );
		m_pBridgeImpl->addError( sMessage );
		OSL_ENSURE( 0 , "type is not an interface" );
		return sal_False;
	}
	
	typelib_InterfaceTypeDescription *pInterfaceType = 0;
	TYPELIB_DANGER_GET(
		(typelib_TypeDescription **)&pInterfaceType , pITypeRef );
	if( ! pInterfaceType )
	{
		OUString sMessage( RTL_CONSTASCII_USTRINGPARAM( "No typedescription can be retrieved for type " ));
		sMessage += pITypeRef->pTypeName;
		m_pBridgeImpl->addError( sMessage );
		OSL_ENSURE( 0 , "urp: unknown type " );
		return sal_False;
	}
	
	if( ! pInterfaceType->aBase.bComplete )
	{
		typelib_typedescription_complete( (typelib_TypeDescription **) &pInterfaceType );
	}

	if( nMethodId < 0 || nMethodId > pInterfaceType->nAllMembers *2 )
	{
		OUString sMessage( RTL_CONSTASCII_USTRINGPARAM( "vtable out of range for type " ));
		sMessage += pITypeRef->pTypeName;
		sMessage += OUString::createFromAscii( " (" );
		sMessage += OUString::valueOf( (sal_Int32) nMethodId );
		sMessage += OUString::createFromAscii( " )" );
		m_pBridgeImpl->addError( sMessage );

		// (nMethodId > pInterfaceType->nAllMembers *2) is an essential condition
		// for the vtable index to be correct
			OSL_ENSURE( 0 , "vtable index out of range" );
			return sal_False;
	}
		
		// TODO : check the range of nMethodId
	sal_Int32 nMemberIndex = pInterfaceType->pMapFunctionIndexToMemberIndex[ nMethodId ];
	
	if( !( pInterfaceType->nAllMembers > nMemberIndex && nMemberIndex >= 0 ) )
	{
		OUString sMessage( RTL_CONSTASCII_USTRINGPARAM( "vtable out of range for type " ));
		sMessage += pITypeRef->pTypeName;
		sMessage += OUString::createFromAscii( " (" );
		sMessage += OUString::valueOf( (sal_Int32) nMethodId );
		sMessage += OUString::createFromAscii( " )" );
		m_pBridgeImpl->addError( sMessage );
		
		OSL_ENSURE( 0 , "vtable index out of range" );
		return sal_False;
	}

	typelib_InterfaceMemberTypeDescription *pMemberType = 0;
	typelib_typedescriptionreference_getDescription(
		(typelib_TypeDescription **) &pMemberType,pInterfaceType->ppAllMembers[nMemberIndex]);

	if(! pMemberType )
	{
		OUString sMessage( RTL_CONSTASCII_USTRINGPARAM( "unknown method type description for type" ) );
		sMessage += pITypeRef->pTypeName;
		sMessage += OUString::createFromAscii( " (" );
		sMessage += OUString::valueOf( (sal_Int32) nMethodId );
		sMessage += OUString::createFromAscii( " )" );
		m_pBridgeImpl->addError( sMessage );
		
		OSL_ENSURE( 0 , "unknown method type description" );
		return sal_False;
	}
	
	if( typelib_TypeClass_INTERFACE_ATTRIBUTE == pMemberType->aBase.eTypeClass )
	{ 
		*ppAttributeType = (typelib_InterfaceAttributeTypeDescription *) pMemberType;
		*pbIsSetter = ! (
			pInterfaceType->pMapMemberIndexToFunctionIndex[nMemberIndex] == nMethodId );
	}
	else
	{
		*ppMethodType = (typelib_InterfaceMethodTypeDescription *) pMemberType;
	}
	
	TYPELIB_DANGER_RELEASE( (typelib_TypeDescription * )pInterfaceType );
	return sal_True;
}
	
OReaderThread::OReaderThread( remote_Connection *pConnection,
							  uno_Environment *pEnvRemote,
							  OWriterThread * pWriterThread ) :
	m_pConnection( pConnection ),
	m_pEnvRemote( pEnvRemote ),
	m_pWriterThread( pWriterThread ),
	m_bDestroyMyself( sal_False ),
	m_bContinue( sal_True ),
	m_pBridgeImpl((struct urp_BridgeImpl*)
				  ((remote_Context *)pEnvRemote->pContext)->m_pBridgeImpl ),
	m_unmarshal( m_pBridgeImpl, m_pEnvRemote, ::bridges_remote::remote_createStub )
{
	m_pEnvRemote->acquireWeak( m_pEnvRemote );
	m_pConnection->acquire( m_pConnection );
#ifdef DEBUG
	thisCounter.acquire();
#endif	
}


OReaderThread::~OReaderThread( )
{
	m_pEnvRemote->releaseWeak( m_pEnvRemote );
#ifdef DEBUG
	thisCounter.release();
#endif	
}

// may only be called in the callstack of this thread !!!!!
// run() -> dispose() -> destroyYourself() 
void OReaderThread::destroyYourself()
{
	m_bDestroyMyself = sal_True;
	m_pConnection->release( m_pConnection );
	m_pConnection = 0;
	m_bContinue = sal_False;
}

void OReaderThread::onTerminated()
{
	if( m_bDestroyMyself )
	{
		delete this;
	}
}


void OReaderThread::disposeEnvironment()
{
	struct remote_Context *pContext =
		( struct remote_Context * ) m_pEnvRemote->pContext;
	m_bContinue = sal_False;
	if( ! pContext->m_pBridgeImpl->m_bDisposed )
	{				
		uno_Environment *pEnvRemote = 0;
		m_pEnvRemote->harden( &pEnvRemote , m_pEnvRemote );
		if( pEnvRemote )
		{
			pEnvRemote->dispose( m_pEnvRemote );
			pEnvRemote->release( m_pEnvRemote );
		}
		else
		{
			// environment has been disposed eitherway !
		}
	}
}

inline sal_Bool OReaderThread::readBlock( sal_Int32 *pnMessageCount )
{
	m_unmarshal.setSize( 8 );
	if( 8 != m_pConnection->read( m_pConnection , m_unmarshal.getBuffer(), 8 ) )
	{
		OUString s( RTL_CONSTASCII_USTRINGPARAM( "Unexpected connection closure" ) );
		m_pBridgeImpl->addError( s );
		return sal_False;
	}

	sal_Int32 nSize;
	m_unmarshal.unpackInt32( &nSize );
	m_unmarshal.unpackInt32( pnMessageCount );
		
	if( nSize < 0 )
	{
		// buffer too big
		// no exception can be thrown, because there is no thread id, which could be
		// used. -> terminate !
		OUString s( RTL_CONSTASCII_USTRINGPARAM( "Packet-size too big (" ) );
		s += OUString::valueOf( (sal_Int64) (sal_uInt32 ) nSize );
		s += OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
		m_pBridgeImpl->addError( s );
		OSL_ENSURE( 0 , "urp bridge: Packet-size too big" );
		disposeEnvironment();
		return sal_False;
	}

	if( 0 == nSize )
	{
		// normal termination !
		return sal_False;
	}

	// allocate the necessary memory
	if( ! m_unmarshal.setSize( nSize ) )
	{
		OUString s( RTL_CONSTASCII_USTRINGPARAM( "Packet-size too big, couln't allocate necessary memory (" ) );
		s += OUString::valueOf( (sal_Int64) (sal_uInt32 ) nSize );
		s += OUString( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
		m_pBridgeImpl->addError( s );
		OSL_ENSURE( 0 , "urp bridge: messages size too large, terminating connection" );
		return sal_False;
	}
	
	sal_Int32 nRead = m_pConnection->read( m_pConnection , m_unmarshal.getBuffer() , nSize );
	
	if( nSize != nRead )
	{
		OUString s( RTL_CONSTASCII_USTRINGPARAM( "Unexpected connection closure, inconsistent packet (" ) );
		s += OUString::valueOf( (sal_Int64) (sal_uInt32 ) nSize );
		s += OUString( RTL_CONSTASCII_USTRINGPARAM( " asked, " ) );
		s += OUString::valueOf( (sal_Int64) (sal_uInt32 ) nRead );
		s += OUString( RTL_CONSTASCII_USTRINGPARAM( " got )" ) );
		m_pBridgeImpl->addError( s );
		// couldn't get the asked amount of bytes, quit
		// should only occur, when the environment has already been disposed
		OSL_ENSURE( m_pBridgeImpl->m_bDisposed , "urp bridge: inconsistent packet, terminating connection." );
		return sal_False;
	}
	return sal_True;
}

inline sal_Bool OReaderThread::readFlags( struct MessageFlags *pFlags )
{
	sal_uInt8 nBitField;
	if( ! m_unmarshal.unpackInt8( &nBitField ) )
	{
		m_pBridgeImpl->addError( "Unexpected end of message header (1)" );
		return sal_False;
	}

	if( HDRFLAG_LONGHEADER & nBitField )
	{
		// this is a long header, interpret the byte as bitfield
		pFlags->bTid     = (HDRFLAG_NEWTID & nBitField );
		pFlags->bRequest = (HDRFLAG_REQUEST & nBitField);
				
		if( pFlags->bRequest )
		{
			// request
			pFlags->bType = ( HDRFLAG_NEWTYPE & nBitField );
			pFlags->bOid  = ( HDRFLAG_NEWOID & nBitField );
			pFlags->bIgnoreCache = ( HDRFLAG_IGNORECACHE & nBitField );
			pFlags->bMoreFlags = ( HDRFLAG_MOREFLAGS & nBitField );
					
			if( pFlags->bMoreFlags )
			{
				// another byte with flags
				sal_Int8 moreFlags;
				if( ! m_unmarshal.unpackInt8( &moreFlags ) )
				{
					m_pBridgeImpl->addError( "Unexpected end of message header (2)" );
					return sal_False;
				}
				pFlags->bSynchronous = ( HDRFLAG_SYNCHRONOUS & moreFlags );
				pFlags->bMustReply = ( HDRFLAG_MUSTREPLY & moreFlags );
				OSL_ENSURE( pFlags->bSynchronous && pFlags->bMustReply ||
							! pFlags->bSynchronous && !pFlags->bMustReply,
							"urp-bridge : customized calls currently not supported !");
			}
			
			if( HDRFLAG_LONGMETHODID & nBitField )
			{
				// methodid as unsigned short
				if( ! m_unmarshal.unpackInt16( &(pFlags->nMethodId )) )
				{
					m_pBridgeImpl->addError( "Unexpected end of message header (3)" );
					return sal_False;
				}
			}
			else
			{
				sal_uInt8 id;
				if( ! m_unmarshal.unpackInt8( &id ) )
				{
					m_pBridgeImpl->addError( "Unexpected end of message header (4)" );
					return sal_False;
				}
				pFlags->nMethodId = (sal_uInt16) id;
			}
		}
		else
		{
			// reply
			pFlags->bRequest = sal_False;
			pFlags->bException = ( HDRFLAG_EXCEPTION & nBitField );
		}
	}
	else
	{
		// short request
		pFlags->bRequest = sal_True;
		if( 0x40 & nBitField )
		{
			sal_uInt8 lower;
			if( ! m_unmarshal.unpackInt8( &lower  ) )
			{
				m_pBridgeImpl->addError( "Unexpected end of message header (5)" );
				return sal_False;
			}
			pFlags->nMethodId = ( nBitField & 0x3f ) << 8 | lower;
		}
		else
		{
			pFlags->nMethodId = ( nBitField & 0x3f );
		}
	}
	return sal_True;
}

void OReaderThread::run()
{
	// This vars are needed to hold oid,tid and type information, which should not be cached.
	Type lastTypeNoCache;
	OUString lastOidNoCache;
	ByteSequence lastTidNoCache;
	
	while( m_bContinue )
	{
		sal_Int32 nMessageCount;
		if( ! readBlock( &nMessageCount ) )
		{
			disposeEnvironment();
			break;
		}

		uno_Environment *pEnvRemote = 0;
   		m_pEnvRemote->harden( &pEnvRemote , m_pEnvRemote );
		if( !pEnvRemote )
		{
			// environment has been disposed already, quit here
			break;
		}
		ServerMultiJob *pMultiJob = 0;
		remote_Interface *pLastRemoteI = 0;
		while( ! m_unmarshal.finished()  )
		{
#ifdef BRIDGES_URP_PROT
			sal_uInt32 nLogStart = m_unmarshal.getPos();
			sal_Bool bIsOneWay = sal_False;
			OUString sMemberName;
#endif
			MessageFlags flags;

			if( ! readFlags( &flags ) )
			{
				m_pBridgeImpl->addError( "incomplete message, skipping block" );
				OSL_ENSURE ( 0 , "urp-bridge : incomplete message, skipping block" );
				break;
			}

			// use these ** to access the ids fast ( avoid acquire/release calls )
			sal_Sequence **ppLastTid = flags.bIgnoreCache ?
				(sal_Sequence **) &lastTidNoCache :
				(sal_Sequence **) &(m_pBridgeImpl->m_lastInTid);
			rtl_uString **ppLastOid = flags.bIgnoreCache ?
				(rtl_uString ** ) &lastOidNoCache :
				(rtl_uString ** ) &(m_pBridgeImpl->m_lastInOid);
			typelib_TypeDescriptionReference **ppLastType =
				flags.bIgnoreCache ?
				(typelib_TypeDescriptionReference ** ) &lastTidNoCache :
				(typelib_TypeDescriptionReference ** ) &(m_pBridgeImpl->m_lastInType);
			
			// get new type
			if( flags.bType )
			{
				typelib_TypeDescriptionReference *pTypeRef = 0;
				if( m_unmarshal.unpackType( &pTypeRef ) )
				{
					// release the old type
					typelib_typedescriptionreference_release( *ppLastType );
					// set the new type
					*ppLastType = pTypeRef;

					// no release on pTypeRef necessary (will be released by type dtor)
				}
				else
				{
					typelib_typedescriptionreference_release( pTypeRef );
					m_pBridgeImpl->addError( "error during unpacking (maybe cached) interface type" );
					OSL_ENSURE( 0 , "urp-bridge : error during unpacking interface type, terminating connection" );
					disposeEnvironment();
					break;
				}
				if( m_pBridgeImpl->m_lastInType.getTypeClass() != typelib_TypeClass_INTERFACE )
				{
					OUString sMessage( RTL_CONSTASCII_USTRINGPARAM( "interface type is not of typeclass interface (" ));
					sMessage += OUString::valueOf( (sal_Int32) m_pBridgeImpl->m_lastInType.getTypeClass() );
					m_pBridgeImpl->addError( sMessage );
					OSL_ENSURE( 0 , "urp-bridge : not an interface type" );
					disposeEnvironment();
					break;
				}
			}
			if( flags.bOid )
			{
				rtl_uString *pOid = 0;
				if( m_unmarshal.unpackOid( &pOid ) )
				{
					rtl_uString_release( *ppLastOid );
					*ppLastOid = pOid;
				}
				else
				{
					rtl_uString_release( pOid );
					m_pBridgeImpl->addError( "error during unpacking (maybe cached) oid" );
					OSL_ENSURE( 0 , "urp-bridge : error during unpacking cached data, terminating connection" );
					disposeEnvironment();
					break;
				}
			}

			if( flags.bTid )
			{
				sal_Sequence *pSeq = 0;
				if( m_unmarshal.unpackTid( &pSeq ) )
				{
					rtl_byte_sequence_release( *ppLastTid );
					*ppLastTid = pSeq;
				}
				else
				{
					rtl_byte_sequence_release( pSeq );
					
					m_pBridgeImpl->addError( "error during unpacking (maybe cached) tid" );
					OSL_ENSURE( 0 , "urp-bridge : error during unpacking cached data, terminating connection" );
					disposeEnvironment();
					break;
				}
			}

			// do the job
			if( flags.bRequest )
			{
				//--------------------------
				// handle request
				//--------------------------
				// get the membertypedescription
				typelib_InterfaceMethodTypeDescription *pMethodType = 0;
				typelib_InterfaceAttributeTypeDescription *pAttributeType = 0;
				sal_Bool bIsSetter = sal_False;
				
				if( getMemberTypeDescription(
					&pAttributeType, &pMethodType, &bIsSetter,
					flags.nMethodId, *ppLastType ) )
				{
					if( ! pLastRemoteI || flags.bOid || flags.bType )
					{
						// a new interface must be retrieved

						// retrieve the interface NOW from the environment
						// (avoid race conditions : oneway followed by release )
						typelib_InterfaceTypeDescription *pInterfaceType = 0;
						
						TYPELIB_DANGER_GET(
							(typelib_TypeDescription ** ) &pInterfaceType ,
							*ppLastType );
						if( !pInterfaceType )
						{
							OUString sMessage( RTL_CONSTASCII_USTRINGPARAM( "Couldn't retrieve type description for type " ) );
							sMessage += (*ppLastType)->pTypeName;
							m_pBridgeImpl->addError( sMessage );
							delete pMultiJob;
							pMultiJob = 0;
							disposeEnvironment();
							pLastRemoteI = 0; // stubs are released during dispose eitherway
							break;
						}
						pEnvRemote->pExtEnv->getRegisteredInterface(
							pEnvRemote->pExtEnv, ( void **  ) &pLastRemoteI,
							*ppLastOid, pInterfaceType );
						TYPELIB_DANGER_RELEASE( (typelib_TypeDescription * )pInterfaceType );

						if( !pLastRemoteI &&
							REMOTE_RELEASE_METHOD_INDEX != flags.nMethodId &&
							0 == rtl_ustr_ascii_compare_WithLength(
								(*ppLastOid)->buffer, (*ppLastOid)->length, g_NameOfUrpProtocolPropertiesObject ) )
						{
							// check for bridge internal propertyobject
							pLastRemoteI = m_pBridgeImpl->m_pPropertyObject;
							pLastRemoteI->acquire( pLastRemoteI );
							flags.bBridgePropertyCall = sal_True;
						}
							
						// NOTE : Instance provider is called in the executing thread
						//        Otherwise, instance provider may block the bridge
					}

					sal_Bool bCallIsOneway = sal_False;
					if( flags.bMoreFlags )
					{
						// flags override the default !
						bCallIsOneway = ! flags.bSynchronous;
					}
					else if( pMethodType && pMethodType->bOneWay )
					{
						bCallIsOneway = sal_True;
					}
					
					if( pMultiJob && ! flags.bTid && bCallIsOneway && ! pMultiJob->isFull())
					{
						// add to the existing multijob, nothing to do here
					}
					else
					{
						// create a new multijob
						if( pMultiJob )
						{
							// there exists an old one, start it first.
							pMultiJob->initiate();
						}
						
						pMultiJob = new ServerMultiJob(
							pEnvRemote, *ppLastTid,
							m_pBridgeImpl, &m_unmarshal , nMessageCount );
					}

					pMultiJob->setIgnoreCache( flags.bIgnoreCache );
					pMultiJob->setType( *ppLastType );
					if( pMethodType )
					{
						pMultiJob->setMethodType( pMethodType ,
												  REMOTE_RELEASE_METHOD_INDEX == flags.nMethodId,
												  bCallIsOneway );
					}
					else if( pAttributeType )
					{
						pMultiJob->setAttributeType( pAttributeType, bIsSetter, bCallIsOneway );
					}
					else
					{
						OSL_ASSERT( 0 );
					}

					if( pLastRemoteI )
						pMultiJob->setInterface( pLastRemoteI );
					else
						pMultiJob->setOid( *ppLastOid );
				} /* getMemberTypeDescription */
				else
				{
					delete pMultiJob;
					pMultiJob = 0;
					pLastRemoteI = 0; // stubs are released during dispose eitherway
					disposeEnvironment();
					break;
				}
#ifdef BRIDGES_URP_PROT
				bIsOneWay = pMethodType && pMethodType->bOneWay;
				sMemberName = pMethodType ?
					pMethodType->aBase.pMemberName :
					pAttributeType->aBase.pMemberName;
				sal_uInt32 nLogHeader = m_unmarshal.getPos();
#endif
				if( ! pMultiJob->extract(  ) )
				{
					// severe error during extracting, dispose
					delete pMultiJob;
					pMultiJob = 0;
					pLastRemoteI = 0; // stubs are released during dispose eitherway
					disposeEnvironment();
					break;
				}

#ifdef BRIDGES_URP_PROT				
				urp_logServingRequest(
					m_pBridgeImpl, m_unmarshal.getPos() - nLogStart,
					m_unmarshal.getPos() - nLogHeader,
					!bIsOneWay,
					sMemberName );
#endif
				if ( flags.bBridgePropertyCall )
				{
					// call to the bridge internal object.
					// these calls MUST be executed within the dispatcher thread in order
					// to synchronize properly with protocol changes
					// NOTE : Threadid is not preserved for this call.

					// lock the marshaling  NOW !
					{
						MutexGuard guard( m_pBridgeImpl->m_marshalingMutex );
						
						pMultiJob->execute();

						if( m_pBridgeImpl->m_pPropertyObject->changesHaveBeenCommited() )
						{
							Properties props;
							props = m_pBridgeImpl->m_pPropertyObject->getCommitedChanges();

							// This call modified the protocol, apply the changes NOW !
							m_pBridgeImpl->applyProtocolChanges( props );
						}
					}
					delete pMultiJob;
					pMultiJob = 0;
				}
			}
			else
			{
				//--------------------------
				// handle reply
				//--------------------------
				if( pMultiJob )
				{
					pMultiJob->initiate();
					pMultiJob = 0;
				}
				if( pLastRemoteI )
				{
					pLastRemoteI->release( pLastRemoteI );
					pLastRemoteI = 0;
				}
				ClientJob *pClientJob =
					m_pBridgeImpl->m_clientJobContainer.remove(	*( ByteSequence * )ppLastTid );

				// Bridge MUST be already disposed, otherwise we got a wrong threadid
				// from remote !
				OSL_ASSERT( pClientJob || m_pBridgeImpl->m_bDisposed );
				if( ! pClientJob )
				{
					OUStringBuffer error( 128 );
					error.appendAscii( "ThreadID " );
					OString o = byteSequence2HumanReadableString( *(ByteSequence* )ppLastTid );
					error.appendAscii( o.getStr(), o.getLength() );
					error.appendAscii( " unknown, so couldn't unmarshal reply" );
					m_pBridgeImpl->addError( error.makeStringAndClear() );
					pLastRemoteI = 0;
					disposeEnvironment();
					break;
				}
				
				pClientJob->m_bExceptionOccured = flags.bException;

				pClientJob->setUnmarshal( &m_unmarshal );
#ifdef BRIDGES_URP_PROT
				sMemberName = pClientJob->m_pMethodType ?
					pClientJob->m_pMethodType->aBase.pMemberName :
					pClientJob->m_pAttributeType->aBase.pMemberName;
				sal_uInt32 nLogHeader = m_unmarshal.getPos();
#endif
				if( ! pClientJob->extract(  ) )
				{
					// severe error during extracting, dispose
					pLastRemoteI = 0; // stubs are released during dispose eitherway
					disposeEnvironment();		
					break;
				}
#ifdef BRIDGES_URP_PROT
				urp_logGettingReply(
					m_pBridgeImpl, m_unmarshal.getPos() - nLogStart,
					m_unmarshal.getPos() - nLogHeader, sMemberName );				
#endif
				sal_Bool bBridgePropertyCallAndWaitingForReply =
					m_pBridgeImpl->m_pPropertyObject->waitingForCommitChangeReply() &&
					pClientJob->isBridgePropertyCall();
				
				pClientJob->initiate();
				
				if( bBridgePropertyCallAndWaitingForReply )
				{
					// NOTE : This must be the reply for commit change. The new properties
					//        are now applied by the clientJob thread, but the reader thread
					//        must wait for it, because the next message on the wire already
					//        uses the new protocol settings.
					// waiting for the commit change reply
					m_pBridgeImpl->m_pPropertyObject->waitUntilChangesAreCommitted();
				}
			}
		}  // end while( !m_unmarshal.finished() )

		if( pLastRemoteI )
			pLastRemoteI->release( pLastRemoteI );
		
		if( pMultiJob )
			pMultiJob->initiate();

   		if( pEnvRemote )
   			pEnvRemote->release( pEnvRemote );
	}

	if( m_pConnection )
	{
		m_pConnection->release( m_pConnection );
		m_pConnection = 0;
	}
}
}

Attachment: pgpeZkiBgVJw1.pgp
Description: PGP signature


Reply to: