Operating System - OpenVMS
1827775 Members
2601 Online
109969 Solutions
New Discussion

Re: Berkley Sockets Programming on VMS

 
SOLVED
Go to solution

Berkley Sockets Programming on VMS

I am writing a program to talk to a PC-base system using Berkley Sockets. My program runs until I get an error message that there are no more I/O channels. The debug messages indicate that the "close(sockfd)" call is not closing the socket connection. As the program loops, it creates a new socket and I eventually run out of I/O channels. Does anyone know why the "close(sockfd)" call would not work?
20 REPLIES 20
Hoff
Honored Contributor

Re: Berkley Sockets Programming on VMS

Bogus channel data in the argument? There are various reasons. Check the errno value, etc.
Hein van den Heuvel
Honored Contributor

Re: Berkley Sockets Programming on VMS


>> Does anyone know why the "close(sockfd)" call would not work?

One has to assume that the function itself normally does work, and thus suspect your program. Why does it not work for you?
A couple of potential causes in otrder of likelyhood...
1) because it is not called at all
2) because it is with the wrong argument? (value vs reference)
3) because it is called with the right argument at the wrong time? (busy io?)

If dynamic, online, debugging is difficult, then I would be tempted to sprinkle is with some print statement:
- After each socket call to displaying the returned socket descriptor value, and possibly a timestamps (seconds?)
- Just before that close call, again dislaying the value of 'sockfd' (.
- After the close, the status and errno of that status = -1 ( EBADF ? EINTR ? )
... the program _does_ check the return value on the close right?

And make those prints really adjacent, not a function level up!

Good luck debugging.

For further help you may want to attach a few snippets of code arounf the open and close calls and the parameters used by them

I'm sure you know this, but all the function are in Help. For example:
$HELP TCPIP_SERVICES Programming_Interfaces Socket_API_Functions socket()
$HELP TCPIP_SERVICES Programming_Interfaces Socket_API_Functions close

fwiw,
Hein.

John Gillings
Honored Contributor

Re: Berkley Sockets Programming on VMS

Patrick,

Use SDA (ANALYZE/SYSTEM) to look at what channels your program is using:

$ ANALYZE/SYSTEM
SDA> SET PROCESS/INDEX=pid
SDA> SHOW PROCESS/CHANNEL

At the least, you can confirm that it's the IP sockets you're running out of. Consider there may be other consumers of channels in the loop that you didn't notice.
A crucible of informative mistakes
Robert Gezelter
Honored Contributor

Re: Berkley Sockets Programming on VMS

Patrick,

WADU, Occam's Razor would seem to indicate that the calls to close have a problem.

I would recommend adding debugging output to the open and close calls to check the returns and parameters.

The most common C error is de-referencing. Are you sure that your program is actually passing the correct channel number to close?

- Bob Gezelter, http://www.rlgsc.com

Re: Berkley Sockets Programming on VMS

Good morning all:

Here is the latest. I stripped down the program to include only the socket() call and the close() call. Since my favorite way of debugging on a VAX is thru print statements, here is the output of my little program.

SO1CP1$ run testopenclose
02/23/2007 06:31:36 Test: Created sockfd = 144
02/23/2007 06:31:36 Test: Failed to close connection: bad file number
02/23/2007 06:31:36 Test: Close socket = close(144)
02/23/2007 06:31:36 Test: errno = 9

errno = 9 = EBADF

After 30 years of programming, you would think that I would be able to write a program that creates a socket and then closes it successfully !

So, how can the socket file descriptor get "bad" even when I don't do anything with it? The socket descriptor is an "int". Its value after the socket() it he same as is used in the close() call. This program is simple and it should work, but it doesn't.

Please ignore the fact that the VAX has not, as yet, sprung forward for Day Light Savings.
Steven Schweda
Honored Contributor

Re: Berkley Sockets Programming on VMS

[...] you would think [...]

Perhaps I would, and perhaps I wouldn't.
Without seeing the program, and how it was
compiled and linked, I probably wouldn't
think very much.

Re: Berkley Sockets Programming on VMS

PS - Here are the messages that were on the console this morning when I got in.

{date & timestamp} Failed to create socket: non-translatable vms error code: 0x1B4, vms message: %SYSTEM-F-NOIOCHAN, no i/o channel available
%NONAME-F-NOMSG, message number 00000002
Robert Gezelter
Honored Contributor

Re: Berkley Sockets Programming on VMS

Patrick,

Please post the source code for your sample program.

- Bob Gezelter, http://www.rlgsc.com

Re: Berkley Sockets Programming on VMS

Here is the plain and simple "testopenclose.c" program.

#include /* define internet related constants, */
/* functions, and structures. */
#include /* define network address information */
#include /* define network database library info */
#include /* define BSD socket api. */
#include /* define standard io functions. */
#include /* define standard library functions. */
#include /* define string handling furnctions. */
#include /* needed for the SLEEP function. */
#include
#include


int main()
{
int sockfd;
char strDateTime[24];
char strPerrorMsg[256];

/*
* get the current date and time stamp for use on output messages.
*/
getCurrentTime (strDateTime);

/*
* create a socket
*/
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
{
strcpy (strPerrorMsg, strDateTime);
strcat (strPerrorMsg, "Test: Failed to create socket");
perror (strPerrorMsg);
exit (EXIT_FAILURE);
}
printf ("%sTest: Created sockfd = %d\n", strDateTime, sockfd);

/*
* close a socket
*/
if ( close (sockfd) < 0 )
{
strcpy (strPerrorMsg, strDateTime);
strcat (strPerrorMsg, "Test: Failed to close connection");
perror (strPerrorMsg);
printf ("%sTest: Close socket = close(%d)\n", strDateTime, sockfd);
}

printf ("%sTest: errno = %d\n", strDateTime, errno);

exit (EXIT_SUCCESS);
}


And here is how I compile and link it:
SO1CP1$ type buildtestopenclose.com
$!
$ cc testopenclose.c /obj=*.obj
$ LINK testopenclose.OBJ,-
getCurrentTime.obj,-
TCPIP$LIBRARY:TWGLIB.OLB/LIB,-
OI:OILLIB.OLB/LIB,SS:SSLIB.OLB/LIB -
/EXE=testopenclose.EXE
$!

I would definitely appreciate any help I can get. I contracting with a company and my contract is over at the end of March. I would like to leave knowing this program works.
Steven Schweda
Honored Contributor

Re: Berkley Sockets Programming on VMS

> [...] TCPIP$LIBRARY:TWGLIB.OLB [...]

HOLY COW! There's a blast from the past.

Have you tried plain-old LINK?

alp $ cc TESTOPENCLOSE.C

getCurrentTime (strDateTime);
.........^
%CC-I-IMPLICITFUNC, In this statement, the identifier "getCurrentTime" is implic
itly declared as a function.
at line number 24 in file ALP$DKA0:[SMS]TESTOPENCLOSE.C;1
alp $ link TESTOPENCLOSE
%LINK-W-NUDFSYMS, 1 undefined symbol:
%LINK-I-UDFSYM, GETCURRENTTIME
%LINK-W-USEUNDEF, undefined symbol GETCURRENTTIME referenced
in psect $LINK$ offset %X00000090
in module TESTOPENCLOSE file ALP$DKA0:[SMS]TESTOPENCLOSE.OBJ;2

Note the lack of unresolved socket() stuff?

Unless you're actually using the Wollongong/
Attachmate PathWay TCP/IP product, that is.

The full explanation of the misbehavior
involves the implementation of socket() and
friends in the PathWay run-time stuff.
Robert Gezelter
Honored Contributor

Re: Berkley Sockets Programming on VMS

Patrick,

Beyond your program:
- What architecture are you using? (VAX/ALPHA/IA-64)
- What Version of the system are you using?
- What IP stack are you using?

- Bob Gezelter, http://www.rlgsc.com
Steven Schweda
Honored Contributor
Solution

Re: Berkley Sockets Programming on VMS

Some fine print:

You're either using the wrong (non-PathWay)
header files, or else you're using the wrong
(PathWay) TCP/IP run-time library. It would
take me a while to check the details, but as
I recall, you'd need to be using netclose()
instead of plain close() with the PathWay
stuff. (And netread() and netwrite() instead
of read() and write(), but recv() is ok.) No
bets, however, as I haven't touched code like
that in a long time.
Hein van den Heuvel
Honored Contributor

Re: Berkley Sockets Programming on VMS

That simpel test program (of course) works fine on my I64 OpenVMS 8.3 with NO special options on the link.

All I changed was to add a dummy function:
getCurrentTime (char *strDateTime)
{
strcpy ( strDateTime, "Hein Test" );
}

I suspect you accidently used a 'socket' from one library and a 'close' from an other.

I reccomend a to link with /MAP/CROSS to see where stuff is being resolved.
You may need some library re-ordering or /SELECT or explicit module inclusion.

Forgot the old standby questions:
- Did this ever work for you?
- What changed recently?

Regards,
Hein van den Heuvel

Re: Berkley Sockets Programming on VMS

The computer is a VAXstation 9000-40 circa 1993 running a "Plant Monitoring System" (PMS) software package by ABB (which ABB no longer supports!). So, it is a VAX architecture.

Operating System VAX/VMS version 5.5-2

I don't know how to find out what IP stack I am using. I never took a sys admin course.

My customer is a power generation company, and as in all industrial environments, they run their computers until they die from obsolesence.

I tried a plain link, but SOCKET was undefined.
SO1CP1$ link testopenclose.obj,getcurrenttime.obj
%LINK-W-NUDFSYMS, 1 undefined symbol:
%LINK-I-UDFSYM, SOCKET
%LINK-W-USEUNDEF, undefined symbol SOCKET referenced
in psect $CODE offset %X00000026
in module TESTOPENCLOSE file SYS$SYSDEVICE:[PMS.DESIGNER.HENRY.CALDON]TESTOPENCLOSE.OBJ;7

Using sockets, I have been able to :
1) create a socket
2) connect the socket to an IP address/Port #
3) write to my simulator
4) read data from my simulator
5) process the data to the PMS database

But I can't close the socket. I am now thinking that I may have to rewrite the program to use QIO calls. The ABB PMS software package has programs which are using QIO calls. But since this computer is scheduled to be replaced in a couple of years, I wanted to write my program to use the least amount of VMS-specific code as possible. I am assuming that the replacement will be PC-based running Windows or Linux or some other Op Sys. Since, I am contracting with this company and my contract is up at the end of the month, I wanted to make the porting of my code by someone else as simple as possible.

I will check into the netclose() call. Thanks for all of the suggestions and ideas. And I am glad to have triggered some old, but fond, memories for some of you.

Re: Berkley Sockets Programming on VMS

netclose() worked!!!

SO1CP1$ @buildtestopenclose
SO1CP1$ run testopenclose
02/23/2007 08:30:39 Test: Created sockfd = 144
02/23/2007 08:30:39 Test: errno = 0

Thank you all. This saves me from having to rewrite using QIO calls.

Now I can run my "overnight" test to see how well my programs are doing.
Hein van den Heuvel
Honored Contributor

Re: Berkley Sockets Programming on VMS

>> I tried a plain link, but SOCKET was undefined.


Yeah... but if that is the full linker message, then CLOSE apparently _was_ resolved from somewhere. So you are picking up a wrong close.

btw.. In the current DECC compiler, that socket and close call would actually call out to functions decc$socket and decc$close resolved in DECC$SHR

Hein.

Steven Schweda
Honored Contributor

Re: Berkley Sockets Programming on VMS

> VAX/VMS version 5.5-2

That was useful. It's old enough to make
PathWay (formerly known as WIN/TCP) more
likely.

> I don't know how to find out what IP stack
> I am using.

Well, if you had some reason to specify
TWGLIB.OLB, I'd guess that
SHOW LOGICAL TWG*
would say something.

I'm working from memory here (because
starting up my VAXstation 2000 would take
such a long time), but you probably need to
fetch your header files from somewhere under
TWG$TCP:[NETDIST], which can be done in a
number of ways (CC /INCLUDE, among them).

There may even be a *version*.exe around
there somewhere, which would identify it a
little more precisely.

Kermit does this:

[...]
#ifdef WINTCP

#include
#include
#include
#include
/*
The WIN/TCP code path is the same as that for MultiNet.
Only the routine names have changed ...
*/
#define socket_errno errno
#define socket_read netread
#define socket_ioctl ioctl
#define socket_write netwrite
#define socket_perror win$perror
#define socket_close netclose

#else /* Not WINTCP */
[...]

which should offer some clues.

> [..,] fond [...]

Well, PathWay (WIN/TCP) worked a lot better
then the DEC UCX product in those days, so I
was fond_er_ of it than some other things.

> [...] I may have to rewrite the program to
> use QIO calls.

I would try hard to avoid that.
Hoff
Honored Contributor

Re: Berkley Sockets Programming on VMS

In all likelyhood, you are slamming into some limit in whatever IP package is installed in this box.

To extend what Hein has written, get rid of those other libraries to start with (until and unless those are required by the particular IP stack installed on your OpenVMS system), and I'd also encourage a trip through the OpenVMS debugger -- the latter to get a better look at what the code is doing.

In particular:

$ cc testopenclose.c /DEBUG
$ cc getCurrentTime.c /DEBUG
$ LINK /DEBUG -
/EXE=testopenclose.EXE -
testopenclose.OBJ,-
getCurrentTime.obj
$

The basic problem here is that software this old is not going to be easy to deal with, and it's not going to be portable. Whatever documentation was available is likely long gone. What you've got *should* work, so whatever IP package is here is not working as intended -- you may well be crossing routines from different packages or other such weirdness.

I'd look at porting the code forward to a newer version, assuming the upgraded equivalent or alternative LPs are available.

http://64.223.189.234/node/98

But that's not likely going to fit within the next month, save as a parallel effort to get the code moving on a more current release. (That would be a fun and interesting project; factory floor stuff is seemingly always rather entertaining.)

Porting forward is usually pretty easy, even with $qio calls and other such. I haven't looked to see what packages and offerings are available from ABB, though BASEstar and other environments are certainly around.

Coding for portability is arguably a waste of your remaining time, at least until a decision is made to port forward or port to another platform. (That grates, I know. It bugs me too. But low-level incremental retrofits of portability are not necessarily a good business case -- at least until you know that the code will be reused.)

Here? I'd use $qio given the schedule. That unless I could find other code that uses the sockets -- and I might infer that the existing code used $qio because sockets didn't work in this old code. Not a certainty; who knows what those original programmers knew.)

Stephen Hoffman
HoffmanLabs
Steven Schweda
Honored Contributor

Re: Berkley Sockets Programming on VMS

One more dim recollection/guess: That "144"
is a VMS channel number, which is why it
isn't closer to the 3, 4, 5, ... range, which
might be expected in this context. And
that's why it made no sense to the normal C
RTL close().

> Thank you all. [...]

Where should I send the bill?

Re: Berkley Sockets Programming on VMS

I probably should have closed this thread earlier. Thanks for your help.