Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

bind error 125: EADDREINUSE. Please help !

245 views
Skip to first unread message

Ravi Bhave

unread,
Jun 3, 2003, 6:29:03 PM6/3/03
to
Hi Gurus,

Sorry if I have confused you by posting incomplete code. I am in the
process of porting some programs from HP UX11 to SunSolaris. The code
is working fine for last several years on HP. It took me a while to
figure out that there is no function which gives me the list of all
processes running on Sun machine similar to pstat_getproc available on
HP UX. I an now reading the /proc directory and scanning out all the
processes and loading the relevant in my LoadList code.

I passed the error Address Family not supported.. but bind is still
failing with error 125: EADDREINUSE

My main program is error_log.C In the main program I check and open a
socket, bind it to recieve the message. The code is failing NOW at
bind call with address is in use error. The detail code is as
follows.

Please review and advise me as I am desperately in need to get this
working.
Many thanks in advance.
Ravi

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
error_log.C
.....
......
// Check that we are the only one using the socket:
// Make sure we are the only copy running with this socket:
if ( IsSocketUsed( GetSocketName() ) ) {
cerr << "Socket: " << GetSocketName() <<
" is already in use." << endl;
throw ( FAIL );
}

// Setup the receive socket to default path and bind to the
socket ID:
if ( MesgIn.Open( GetSocketName() ) != SUCCESS ) {
cerr << "Failed to setup receive socket" << endl;
throw ( FAIL );
}

// GetSocketName gets the program name (basename) error_log.
// IsSocketUsed calls LoadList and loads the process information in
process structure
// MesgIn.Open code is where the program is failing.
MesgIn.Open code is enclosed at the end.

// WHEN I RUN THIS PROGRAM WITH SEVERAL COUT I GET THE FOLLOWING ERROR
125

(aho0mqdev)[/ford/thishost/u/rbhave/mqrouter/error_log]$ ./error_log
3rd sockfd 3status = 0
Status = -1 3 0x4748a 16 errno = 125
eacces 13
eio 5
eisdir 21
eaddrinuse 125
eaddrnotavial 126
ebadf 9
einval 22
enosr 63
enosock 95
eloop 90
enoent 2
enotdir 20
erofs 30
5th fail
Failed to setup receive socket
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The code for IsSocketUsed is as follows:
// -------------------------------------------------------------------------
// NAME
// IsSocketUsed
//
// DESCRIPTION
// Determines if SockName is used by a running process.
// A socket is used if a program is found with the same name as
the socket
.
// A socket is used if a program is found in the ps list and it
has
// a -S<name> argument where <name> is the socket name.
// The user defaults to the current user.
//
// ARGUMENTS
// SockName This is the name of the socket to check for.
// User This is the optional name of the user to use
as a mask
// in our search. If the User is
defaulted
(to null ptr)
// then we use the username of
the current
process.
// If the User is passed as
PROC_ALL_USERS, then al
l users
// are checked.
//
// RETURNS
// TRUE if the socket was found in use.
// FALSE otherwise.
//
// SIDE EFFECTS
// The calling process will be excluded in the search. This is
done by
// examining the pid of each process in the list and
excluding us
// The program name searched for will always be the base name of
the progr
am
// ignoring any path which may have been used when the
program was
// started.
//
// LIMITS
// ------------------------------------------------------------------------
bool_t IsSocketUsed(
const char *SockName,
const char *User_p )
{
PsList_c PsList; // PsList is a local structure to store
information
String User;

// Default argument means this user only:
if ( User_p == cpNULL ) {
User = GetUserName();
}
// A specific user means search for that user:
// or
// All users means we must search the entire ps list as we are
looking
// for arguments as well as program names:
else {
User = User_p;
}
PsList.LoadList( User.Get() ); // LoadList Loads the process
information
// in the process structure
code
// included at the end.
int PsIdx;
for ( PsIdx = 0; PsIdx < PsList.NumItems(); PsIdx++ ) {
if ( strcmp( PsList[PsIdx].Socket, SockName ) == 0 ) {
Pid = (pid_t) PsList[PsIdx].Pid;
return TRUE;
}
}
Pid = 0;
return FALSE;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// Load the internal list from the system process table.
void PsList_c::LoadList( const char *UserName )
{
long Uid( 0 );
struct passwd PwEntry;
struct passwd *pPwEntry;
Psi is loacal declared structrred to store information.
// The following structure is used for each process item
retrieved:
struct PsItem_t {
char Cmd[PST_CLEN];
char Name[PST_CLEN];
char Socket[PST_CLEN];
long Pid;
long PPid;
long Start;
long Cpu;
long Size;
}; // Psi


// Get the UID we wish to use as a filter. Default to running
process.
if ( UserName == cpNULL ) {
Uid = getuid();
}
else if ( strcmp( UserName, PROC_ALL_USERS ) == 0 ) {
Uid = 0;
}
else {
pPwEntry = getpwnam( UserName );
if ( pPwEntry == (struct passwd *) 0 ) {
Uid = getuid();
}
else {
PwEntry = *pPwEntry;
Uid = PwEntry.pw_uid;
}
}
long PageSize = sysconf( _SC_PAGE_SIZE );
char Buf[PST_CLEN + 1];
PsiStat_t Psinfo; // system defined structure
int idx( 0 );
int count;
// Identify us:
pid_t MyPid = getpid();
// Reset the number of items in our list:
NumPsItems = 0;
String ProgName;
String SocketName;
static char SepList[] = " "; // separator list for
strtok
String Filename;

// The argument string to look for:
String SocketSwitch( "-" );
SocketSwitch << SWITCH_SOCKET;
Directory_c proc_directory;
int RetValue;
const char * GetProcDirName();
char buf[100];
int fd;
DIR *dirp;
struct dirent *dp;
char *cp = getenv(CMMS_PROC_DIR);
dirp = opendir(cp);
if ( dirp == NULL ) {
cout << " Can not open directory " << endl;
}
while ( ( dp = readdir(dirp)) != NULL ) {
if (( strcmp(dp->d_name, ".") == 0 ) ||
( strcmp(dp->d_name, "..") == 0 )) {
continue;
}
sprintf( buf, "/proc/%s/psinfo",dp->d_name);
fd = open(buf, O_RDONLY);
if ( fd < 0 ) {
perror(buf);
exit(1);
}
read(fd, &Psinfo, sizeof(psinfo_t));

if ( ( Psinfo.pr_uid == Uid || Uid == 0 ) &&
Psinfo.pr_pid != My
Pid ) {
PsItem_t Psi;
char *pWord;
strcpy( Buf, Psinfo.pr_psargs );
pWord = strtok(Buf, SepList );
const char *base = basename( pWord );
if ( pWord == cpNULL ) {
continue;
}
if ( *base == '-' ||
strcmp( base, "ps" ) == 0 ||
strcmp( base, "sh" ) == 0 ||
strcmp( base, "ksh" ) == 0 ||
strcmp( base, "csh" ) == 0 ||
strcmp( base, "tcsh" ) == 0 ||
strcmp( base, "nice" ) == 0 ) {
continue;
}
// Set the program name to the actual program
until we
// search for a socket argument:
ProgName = base;
SocketName = base;
// search for socket argument:
while ( ( pWord = strtok( cpNULL, SepList ) )
!= cpNULL
) {
if ( strncmp( SocketSwitch.Get(),
pWord,
SocketSwitch.Length() ) == 0 )
{
// If the socket name is part
of the wor
d, then use it:
if ( strlen( pWord ) >
SocketSwitch.Leng
th() ) {
SocketName = pWord +
SocketSwitc
h.Length();
break;
}
// Otherwise, it must be the
next word s
o get it:
pWord = strtok( cpNULL,
SepList );
if ( pWord != cpNULL ) {
SocketName = pWord;
break;
}
}
}
// Store the details of each program item in
our list:
strcpy( Psi.Name, ProgName.Get() );
strcpy( Psi.Name, Psinfo.pr_psargs);
strcpy( Psi.Socket, SocketName.Get() );
Psi.Pid = Psinfo.pr_pid;
Psi.PPid = Psinfo.pr_ppid;
Psi.Size = Psinfo.pr_size;
if ( NumPsItems >= ArraySize ) {
ExtendArray();
}
pPsItem[NumPsItems] = Psi;
NumPsItems++;
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// -------------------------------------------------------------------------
// NAME
// Open
//
// DESCRIPTION
// Bind the socket to a name. This creates a socket file which
is used
// as the sink for messages sent to this process.
//
// ARGUMENTS
// Name Character string containing the name of the
socket. This
// cannot be defaulted.
// Path Char string containing the name of the
directory in whic
h
// the socket will be created.
Defaults to
the directory
// in the environment SOCKET_DIR.
If this i
s not set, defaults
// to DEFAULT_SOCKET_DIR.
// BufSize Size of the receive buffer. This should be
large enough
// to support all messages that
will be sen
t to this process
// taking into account those that
will be b
uffered while this
// process is executing. Defaults
to DEFAUL
T_SOCKET_BUF_SIZE.
//
// RETURNS
// SUCCESS if no errors
// FAIL if we could not create the socket file.
//
// SIDE EFFECTS
// If the socket already exists, it will be deleted and
re-created. The
// IsSocketUsed() function checks if the socket is
already in use a
nd
// if it is, an error is returned.
//
// LIMITS
// ------------------------------------------------------------------------
AppErr_t SocketRecv_c::Open(
const char *Name,
const char *Path,
const int BufSize )
{
if ( IsSocketUsed( Name ) ) {
ErrLogWrite( EL_SYS, String( "SocketRecv_c::Open: " <<
Socket: " << Name << " is in use which meansthis" <<
" program may already be running." );
return ( FAIL );
}

// Check if socket open:
if ( SockFd < 0 ) {
if ( SocketDgram_c::Open() != SUCCESS ) {
ErrLogWriteErrno( EL_SYS,String("SocketRecv_c::Open:")
<< "Failed to open underlying socket");
return FAIL;
}
}
int Status;
Status = setsockopt(
SockFd,
SOL_SOCKET,
SO_RCVBUF,
&BufSize,
sizeof ( BufSize ) );
if ( Status != 0 ) {
ErrLogWriteErrno( EL_SYS, String( "SocketRecv_c::Open:" ) <<
"Failed to set buffer size of receive socket");
return ( FAIL );
}
SetSockPath( Path );
SetSockName( Name );
// If the socket already exists with a different user to the current
// one, then FAIL
struct stat FileBuf;
if ( stat( SockAddr_un.sun_path, &FileBuf ) == 0 ) {
uid_t ThisUser = getuid();
if ( FileBuf.st_uid != ThisUser ) {
ErrLogWrite( EL_SYS, String("SocketRecv_c::Open: " ) <<
"Socket already exists for" <<SockAddr_un.sun_path <<
" Previous UID=" << (long) FileBuf.st_uid <<
" This UID=" << (long) ThisUser <<
".This means the previous user did not exit properly or"
<< " is still running. Systems should manually
delete the" << " socket if the previous user has
finished.");
return FAIL;
}
}
BindOK = FALSE;
struct sockaddr_un there = {AF_UNIX, "error_log"};
struct sockaddr_un saddr;
int addr_len = sizeof(saddr);
// (struct sockaddr *) &SockAddr,
Status = bind(
SockFd,
(struct sockaddr *) &there,
addr_len);
cout << "Status = " << Status << " " << SockFd << " " <<
&SockAddr << "
" << sizeof(SockAddr) << "errno = " << errno << endl;
if ( Status < 0 ) {
// If the bind address is in use, then try and delete
it and the
n
// re-create it:
if ( errno == EADDRINUSE ) {
if ( unlink( SockAddr_un.sun_path ) < 0 ) {
ErrLogWriteErrno( EL_SYS, String(
"SocketRecv_c:
:Open: " ) <<
"Failed to unlink bind address for
receiver" <<
", Name=" << SockAddr_un.sun_path
);
cout << " eacces " << EACCES << endl << " eio
" << EIO
<< endl << " eisdir " << EISDIR << endl << "eaddrinuse " <<
EADDRINUSE << endl
<< "eaddrnotavial " << EADDRNOTAVAIL << endl << " ebadf " << EBADF
<< endl <
< "einval " << EINVAL <<endl << " enosr " << ENOSR <<endl << "
enosock " << EN
OTSOCK << endl << " eloop " << ELOOP << endl << "enoent " << ENOENT
<< endl <
< " enotdir " << ENOTDIR << endl << " erofs " << EROFS << endl;
cout << "5th fail" << endl;
return ( FAIL );
}
else {
Status = bind( SockFd, &SockAddr,
sizeof ( SockA
ddr ) );
if ( Status < 0 ) {
ErrLogWriteErrno( EL_SYS,
String( "SocketRecv_c::Open: "
) <<
"Failed in 2nd attempt to bind
for recei
ver" );
cout << "6th fail" << endl;
return ( FAIL );
}
}
}
else {
ErrLogWriteErrno( EL_SYS, String(
"SocketRecv_c::Open: "
) <<
"Failed to bind name to socket" );
cout << "7th fail errno = " << errno << endl;
perror("Error");
return ( FAIL );
}
}
BindOK = TRUE;
// Make the socket read/write for all:
chmod( SockAddr_un.sun_path, 0777 );
return ( SUCCESS );
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

0 new messages