[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::c_plus_plus

Title:C++
Notice:Read 1.* and use keywords (e.g. SHOW KEY/FULL KIT_CXX_VAX_VMS)
Moderator:DECCXX::AMARTIN
Created:Fri Nov 06 1987
Last Modified:Thu Jun 05 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:3604
Total number of notes:18242

3525.0. "Exception handling: targetted catch clause not found (AVMS)" by PTHRED::SHARRIS () Wed Apr 02 1997 18:19

Since we upgraded our cluster to VMS V7.1, we've noticed problems with a
particular test that uses C++ exception handling.  We don't run this test
often, so I don't know if this is related to the V7.1 upgrade or just the
version of C++ or something else. 

We are using C++ V5.3-005, and this problem occurs only on AlphaVMS, altho we
have the same version of C++ on VAX/VMS.   However, our VAX/VMS systems are
still V7.0, not V7.1.  The problem doesn't seem to occur on UNIX either. 

I've read notes 3004, 3032, 3061, 3137 so I know there were problems with
exception handling in this version of C++, but I'm still wondering if this is
the same problem or not.  I haven't seen anything with quite the same signature
error. 

The problem is that when we throw an exception, we get this:

Internal C++ runtime error, targetted catch clause not found.
%DEBUG-I-DYNIMGSET, setting image RB_CONSUMER
%SYSTEM-F-OPCDEC, opcode reserved to Digital fault at PC=0000000000035034, PS=0000001B
break on unhandled exception at CXXL$CALL_CLEANUP+20 in %TASK 5
DBG> show calls
 module name     routine name      line           rel PC           abs PC
                 CXXL$CALL_CLEANUP            0000000000000014 0000000000035034
----- the above appears to be a null frame in the same scope as the frame below
 SKSTREAM                                                    ?                ?
 SKSTREAM                                     0000000000000000 0000000000031908
*RB_CONSUMER     UnitConsumer::MakeRequest
                                  15493       00000000000003CC 0000000000030D94
*RB_CONSUMER     UnitConsumer::TimerCallback
                                  15553       0000000000000028 0000000000031370
*RB_CONSUMER     Timer::TimerAgent
                                  14668       000000000000005C 00000000000301A4

 SHARE$PTHREAD$RTL                            0000000000000000 00000000004E6148
 SHARE$PTHREAD$RTL                            0000000000000000 00000000004D7294
                                              0000000000000000 0000000000000000
----- the above appears to be a null frame in the same scope as the frame below
 SHARE$PTHREAD$RTL                                           ?                ?
                                              0000000000000000 FFFFFFFF83B0B16C
DBG>

Is this a known problem????  Is there anything we can be doing that
would cause this kind of error???

Also note that we get this message when we try running an image that was LINKED
on V7.0: 

run/debug rb_consumer_sav.exe

         OpenVMS Alpha DEBUG Version V7.1-000

%DEBUG-E-INCDSTNES, incorrect DST nesting in module CXXL$VMS_CXX_EXC, compiler error
-DEBUG-I-DSTLOC, error occurs 00001779 bytes from beginning of DST
%DEBUG-I-INITIAL, Language: C, Module: CXXL$VMS_CXX_EXC

DBG>

I know something like this was mentioned in note 3004.*, but when
I tried adding a copy constructor, it seemed to have no affect on
the original accvio.

Part of the code follows, but I'm not including the entire set of sources
because even with them, it's not easy to reproduce the error.  We
only see this error when this 'client' program communicates via RPC
with Resource Broker, causes a server to get started, and then tries to
communicate with the server, and the communication gets an error such that
it throws an exception. It actually happens EVERY time on AlphaVMS
because of the timing, but the setup for you would be fairly brutal.  If you 
can't tell anything from what is here, I'd be glad to work with you on
our version here in ZK2-3.

Thanks,
Sue Harris
======================================
$ cxx /exception=clean/define=PTHREAD_USE_D4 /debug/noopt  /INCLUDE=([])   skstream
Building client executable...
$ cxx /exception=clean/define=PTHREAD_USE_D4 /debug/noopt  /INCLUDE=([]) rb_consumer
$ cxxlink /debug /exe=rb_consumer.exe  rb_consumer.obj, -
                                      skstream.obj, -
                                      sys$library:rb$option.opt/opt, -
                                      sys$input:/opt
SYS$LIBRARY:CMA$OPEN_LIB_SHR/SHARE
SYS$LIBRARY:CMA$LIB_SHR/SHARE
SYS$LIBRARY:CMA$OPEN_RTL/SHARE
SYS$LIBRARY:CMA$RTL/SHARE

// skstream.h
// Copyright (C) 1995, 1996 by John C. Wang. All Rights Reserved.
//
// You may distribute this file with your product in either of two ways:
// IN SOURCE CODE FORM: You must include this file in its entirety.
// IN OBJECT CODE FORM: You must give proper acknowledgements to the author(s)
//   of this program. This may take the form of credits on the start-up screen.
//
// IN ANYCASE, THIS SOFTWARE IS DISTRIBUTED WITHOUT ANY KIND OF EXPLICIT OR
// IMPLICIT WARRANTIES AND THE AUTHORS ARE NOT RESPONSIBLE FOR ANY EVENTS THAT
// OCCURS AS A RESULT OF USING THIS SOFTWARE.
//
// History:
// [JCW 95-Dec-04] created
// [JCW 95-Dec-20] comments added for distribution 95a
// [JCW 96-Jan-01] removed UDP capabilities from skstream

#ifndef __SOCKET_STREAM__
#define __SOCKET_STREAM__

#include <iostream.h>
#ifndef _WIN32
   typedef int SOCKET;
#include <sys/socket.h>
#else
#  include <winsock.h>
#endif

//
// sockbuf
//
class sockbuf : public streambuf
{
public:
	sockbuf( SOCKET & );
	sockbuf( SOCKET &, char *, int );

	virtual ~sockbuf();

	virtual int overflow(int =EOF) ;
	virtual int underflow() ;

        virtual int sync();

protected:
	char *_buffer ;

	// sockbuf specific
	SOCKET &_socket ;
} ;


//
// skstream
//
class skstream : public iostream {
public:
	// constants
	enum service
	{
		ftp         =      21, //tcp
		telnet      =      23, //tcp
		smtp        =      25, //tcp       mail
		time        =      37, //tcp       timserver
		name        =      42, //tcp       nameserver
		nameserver  =      53, //tcp       domain        # name-domain server
		finger      =      79, //tcp
		http        =      80, //tcp
		pop         =     109, //tcp       postoffice
		pop2        =     109, //tcp                     # Post Office
		pop3        =     110, //tcp       postoffice
		nntp        =     119  //tcp       usenet        # Network News Transfer
	} ;

	enum role
	{
		server ,
		client
	} ;

	// methods
	skstream( void );
	skstream( const char *addr, int, const role = client ) ;
	skstream( SOCKET );
	~skstream( void );
      
	void open( const char *addr, const service, const role = client ) ;
	void close( void ) ;
	int is_open( void ) const ;
	void attach( SOCKET = 0 );
	SOCKET getsocket() const ;

	char *getpeername( char * = NULL, int = 0) const ;
	unsigned short getport( void ) const ;
protected:
	SOCKET _socket ;
	sockbuf _sockbuf ;

	// platform dependent library housekeeping          
	inline void init( void ) ;
	inline void shutdown( void ) ;
};

#endif // ndef __SOCKET_STREAM__

// skstream.cpp
// Copyright (C) 1995, 1996 by John C. Wang. All Rights Reserved.
//
// You may distribute this file with your product in either of two ways:
// IN SOURCE CODE FORM: You must include this file in its entirety.
// IN OBJECT CODE FORM: You must give proper acknowledgements to the author(s)
//   of this program. This may take the form of credits on the start-up screen.
//
// IN ANYCASE, THIS SOFTWARE IS DISTRIBUTED WITHOUT ANY KIND OF EXPLICIT OR
// IMPLICIT WARRANTIES AND THE AUTHORS ARE NOT RESPONSIBLE FOR ANY EVENTS THAT
// OCCURS AS A RESULT OF USING THIS SOFTWARE.
//
// History:
// [JCW 95-Dec-04] created
// [JCW 95-Dec-20] comments added for distribution 95a
// [JCW 96-Jan-01] removed UDP capabilities from skstream

#include "skstream.h"
#include <assert.h>

#ifndef _WIN32
#  include <stdlib.h> // NULL && free()
#  include <string.h> // strdup() needed later
#  define  INVALID_SOCKET ( -1 )
#  define  SOCKET_ERROR   ( -1 )
   typedef struct sockaddr_in SOCKADDR_IN;
#  define  SO32
#  define  MPTN
   extern "C" {
#  include <sys/types.h>
#  include <sys/socket.h>
#  include <netinet/in.h>
#  include <netdb.h>
   }
#define sock_init() 0
#include <unistd.h>
#include <arpa/inet.h>
#ifdef __VMS
#define getpeername_size_t size_t
#else
#define getpeername_size_t int
#endif
#else // _WIN32
#define getpeername_size_t int
#endif // _WIN32

#ifdef _DEBUG
	#define dassert(x) assert(x)
	#define debug(x) x
#else
	#define dassert(x)
	#define debug(x)
#endif //def _DEBUG

//
// skstream
//

void skstream::init( void )
{
	// platform dependent initialization
	try {
#ifdef _WIN32

      const WORD wMinVer = 0x0101;	// request v 1.1
		WSADATA wsaData;
		if( 0 != WSAStartup( wMinVer, &wsaData ) )
#else
      if ( sock_init( ) != 0 )
#endif
			throw "Cannot init socket library." ;
	}
	catch( char *error )
	{
		throw error ;
	}
}

void skstream::shutdown( void )
{
	// platform dependent shutdown
	try {
#ifdef _WIN32
      if( 0 != WSACleanup() )
			throw "Cannot shutdown socket library." ;
#else
      return;   
#endif   
   }
	catch( char *error )
	{
		throw error ;
	}
}

skstream::skstream( void ) : _sockbuf( _socket ), iostream( &_sockbuf )
{
	init() ;
	attach( INVALID_SOCKET ) ;
}

skstream::skstream( const char *addr, int port, const role side )
	:_sockbuf( _socket ), iostream( &_sockbuf )
{
	ios::init(&_sockbuf);
	init() ;
	attach( INVALID_SOCKET ) ;
	open( addr, (service)port, side ) ;
}


skstream::skstream( SOCKET sock ) : _sockbuf( _socket ), iostream( &_sockbuf )
{
	init() ;
	attach( sock ) ;
}

skstream::~skstream( void )
         {
	close() ;
	shutdown() ;
}

int skstream::is_open( void ) const
{
	return ( INVALID_SOCKET != getsocket() ) ;
}

void skstream::open( const char *addr, const service port, 
	const role side )
{
	if( is_open() )
		close() ;
	
	try {
                printf ("going to try the create");
		// 1. Create socket
		if( INVALID_SOCKET == ( _socket = ::socket( PF_INET, SOCK_STREAM, 0 ) ) )
			throw "Socket creation error." ;

		// 2. Bind
                printf ("going to try the bind");
		SOCKADDR_IN sa ;
		sa.sin_family = AF_INET ;
#ifdef _WIN32
		sa.sin_addr.S_un.S_addr = INADDR_ANY ;
#else
		sa.sin_addr.s_addr = INADDR_ANY;
#endif
      sa.sin_port = side == client ? 0 : htons( (unsigned short)port ) ;
			// rationale: no client requires fixed port number, so let system assign
		if( SOCKET_ERROR == ::bind( _socket, (sockaddr *)&sa, sizeof( sa ) ) )
			throw "Binding error." ;

		// From now on the two sides are very much different
		if( side == skstream::client )
		{
                        printf ("going to try the connect");
			// 3(cli). Connect
			SOCKADDR_IN sa ;
			sa.sin_family = AF_INET ;

			hostent *he ;

#ifdef _WIN32
			if( NULL == ( he = ::gethostbyname( addr ) ) )
				throw "Cannot resolve remote server." ;

			sa.sin_addr.S_un.S_addr = *(unsigned long *)( he->h_addr_list[ 0 ] ) ;
#else
         /* 
         ** The prototype for BSD (OS/2) sockets has a non-const paramater
         ** for gethostbyname()... any C++ compiler worth squat is going
         ** to choke on an attempt to pass a const char* to a char* :-)
         ** Make a copy of the string locally as a work-around.
         */
         char *tmps = strdup( addr );

         printf ("going to try the gethostbyname");
         if( NULL == ( he = ::gethostbyname( tmps ) ) )
				throw "Cannot resolve remote server." ;

         free( tmps );

         sa.sin_addr.s_addr = *(unsigned long *)( he->h_addr_list[ 0 ] );
#endif         
         sa.sin_port = htons( port ) ;
         printf ("going to try the connect (again)\n");         

			if( SOCKET_ERROR == ::connect( _socket, (sockaddr *)&sa, sizeof( sa ) ) )
				throw "Connection error." ;  <---------------------------------------the error happens here
		}
		else
		{
			// 3(svr). Listen
                        printf ("try listen");
			if( SOCKET_ERROR == ::listen( _socket, 1 ) )
				throw "Listening error." ;

			// 4. Accept
			SOCKET commsock ;
                        printf ("try accept");
			if( INVALID_SOCKET == ( commsock = ::accept( _socket, NULL, NULL ) ) )
				throw "Accepting error." ;
#ifdef _WIN32
         if( SOCKET_ERROR == ::closesocket( _socket ) )
#else
         printf ("try close");
         if( SOCKET_ERROR == ::close( _socket ) )
#endif
         throw "Cannot close server socket." ;
			_socket = commsock ;
		}
	}
	catch( char * )
	{
		// instead of throwing, user will find out by testing is_open()
                printf ("close in catch block");
		close() ;
	}
}

void skstream::close( void )
{
	try {
		if( is_open() )
		{
			_sockbuf.sync() ;
#ifdef _WIN32
			if( SOCKET_ERROR == ::closesocket( _socket ) )
#else
         if( SOCKET_ERROR == ::close( _socket ) )
#endif
				throw "Cannot close socket." ;
		}

		_socket = INVALID_SOCKET ;
	}
	catch( char *error )
	{
		throw error ;
	}
}

void skstream::attach( SOCKET sock )
{
	_socket = sock ;
}

SOCKET skstream::getsocket() const
{
	return _socket ;
}

char *skstream::getpeername( char *buf, int size ) const
{
	try {
		SOCKADDR_IN sa ;
		getpeername_size_t sasize = sizeof( sa ) ;
		if( SOCKET_ERROR ==::getpeername( getsocket(), (sockaddr *)&sa, &sasize ) )
			throw "Cannot get peer name." ;
		if (buf) {
			strncpy( buf, inet_ntoa( sa.sin_addr ), size - 1 ) ;
			return buf ;
			}
		else return inet_ntoa( sa.sin_addr );
	}
	catch( char * )
	{
		return NULL ;
	}
}

unsigned short skstream::getport( void ) const
{
	try {
		SOCKADDR_IN sa ;
		getpeername_size_t sasize = sizeof( sa ) ;
		if( SOCKET_ERROR ==::getpeername( getsocket(), (sockaddr *)&sa, &sasize ) )
			throw "Cannot get peer name." ;
		return ntohs( sa.sin_port ) ;
	}
	catch( char * )
	{
		return ntohs( IPPORT_RESERVED ) ;
	}
}

//
//	sockbuf
//
sockbuf::sockbuf( SOCKET &sock ) : _socket( sock ), streambuf( NULL, 0 )
{
	const int insize = 0x4000 ;		// allocate 16k buffer each for input and output
	const int outsize = 0x4000 ;
	const int bufsize = insize + outsize ;

	_buffer = new char [ bufsize ] ;

	if( this != setbuf( _buffer, bufsize ) )
		_buffer = NULL ;
	else
	{
		setp( _buffer, _buffer + insize ) ;
		setg( _buffer + insize, _buffer + bufsize, _buffer + bufsize ) ;
	}
}

sockbuf::sockbuf( SOCKET &sock, char *buf, int length )
 : _socket( sock ), streambuf( buf, length )
{
	_buffer = NULL ;

	setp( buf, buf + length / 2 ) ;
	setg( buf + length / 2, buf + length, buf + length ) ;
}

sockbuf::~sockbuf()
{
	delete[] _buffer ;
	_buffer = NULL ;
}

int sockbuf::overflow( int nCh )
{
	try
	{
		if( _socket == INVALID_SOCKET )
			throw "Invalid socket!" ;

		if( pptr() - pbase() <= 0 )
			// nothing to send
			return 0 ;

		int size ;
		if( SOCKET_ERROR == ( size = ::send( _socket, pbase(), pptr() - pbase(), 0 ) ) )
			throw "(TCP) Cannot send." ;

		if( size == 0 )
			// remote site has closed this connection
			return EOF ;

		if( nCh != EOF )	// size >= 1 at this point
		{
			size-- ;
			*( pbase() + size ) = nCh ;
		}

		// move remaining pbase() + size .. pptr() - 1 => pbase() .. pptr() - size - 1
		for( char *p = pbase() + size; p < pptr(); p++ )
			*( p - size ) = *p ;
		const int newlen = ( pptr() - pbase() ) - size ;

		setp( pbase(), epptr() ) ;
		pbump( newlen ) ;

		return 0 ;
	}
	catch( char * )
	{
		// instead of throwing, user will find out by testing fail()
		return EOF ;
	}
}

int sockbuf::underflow()
{
	try
	{
		// if get area not empty, return first character
		// else fill up get area and return 1st character

		if( _socket == INVALID_SOCKET )
			throw "Invalid socket!" ;

		if( egptr() - gptr() > 0 )
			return *gptr() ;

		// fill up from eback to egptr
		int size ;
		if( SOCKET_ERROR == ( size = ::recv( _socket, eback(), egptr() - eback(), 0 ) ) )
			throw "(TCP) Receive error." ;

		if( size == 0 )
			// remote site has closed this connection
			return EOF ;

		// move rcvd data from eback() .. eback() + size to egptr() - size .. egptr()
		const int delta = egptr() - ( eback() + size ) ;
		for( char *p = eback() + size - 1; p >= eback(); p-- )
		{
			dassert( p + delta >= eback() ) ;
			dassert( p + delta < egptr() ) ;
			*( p + delta ) = *p ;
		}

		setg( eback(), egptr() - size, egptr() ) ;

		return *gptr() ;
	}
	catch( char * )
	{
		// instead of throwing, user will find out by testing eof()
		return EOF ;
	}
}

int sockbuf::sync()
{
	if( EOF == overflow() )
		return EOF ;	// ios will set the fail bit
	else
	{
		// empty put and get areas
		setp( pbase(), epptr() ) ;
		setg( eback(), egptr(), egptr() ) ;
		
		return 0 ;
	}
}


T.RTitleUserPersonal
Name
DateLines
3525.1can you try 5.4 or 5.5?HNDYMN::MCCARTHYA Quinn Martin ProductionFri Apr 04 1997 11:4015
Following your notes:

3004: 	You say you have added a copy ctor so that should not be the problem
3032:	You don't have any try blocks within the code-example catch blocks
	so that should not be it.
3061: 	You are using /noopt so that should remove this problem
3137:   There isn't a solution posted except "upgrade" and some issues of
	a third party requireing 5.3.

Along those lines - is there any way you can try this using a 5.4 or even a 
5.5 compiler?  If the problem is in the generated exception handling, or
even in the object code provided by the compiler, the answer to a problem
report would be "fixed in next release" (at least I hope it is).

Brian J.
3525.2being workedHNDYMN::MCCARTHYA Quinn Martin ProductionMon Apr 07 1997 11:305
Working this off line (images produced on a OpenVMS V6.2 system using 5.5 
do not show the problem but linking those objects on the other system is 
causing hangs).

bjm