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

Conference turris::decc

Title:DECC
Notice:General DEC C discussions
Moderator:TLE::D_SMITHNTE
Created:Fri Nov 13 1992
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:2212
Total number of notes:11045

2138.0. "perror vs. FAB$L_STV" by DRAGNS::SAUNDERS () Fri Apr 04 1997 18:51

When an RMS$_ACC error occurs on an open() or creat() call, the output of
perror is not very useful. It indicates that errno is EVMSERR and that
vaxc$errno is RMS$_ACC, but there is no way to determine from the output
what the real error was. The real error is in FAB$L_STV.

I know that we can implement an error routine through the "err" keyword in order
to get this information, but I really don't think it should be necessary. One
really shouldn't have to do anything more than:

fd = open("file", O_RDWR, 0600);
if (fd < 0)
{
	perror ("open failed");
	return -1;
}


This comes from a customer problem. The DECdns Advertiser process can't
access files in SYS$SYSTEM:. The code (which is portable) uses perror to the log
file, but the log doesn't tell the Field what the problem was! I had to give
them a program that used the "err" parameter. If the Field had been able to
see what the problem was, they wouldn't have had to call Engineering.


Thanks,
John Saunders
DECdns Engineering
T.RTitleUserPersonal
Name
DateLines
2138.1fixed in V7.1, ECOed for V7.0TAVENG::BORISBoris Gubenko, ISESun Apr 06 1997 13:0422
 You didn't mention the OpenVMS version and whether a CRTL ECO kit was applied.
 After this problem was reported in note 1227 in this conference, the problem
 was fixed in OpenVMS V7.1 main stream.

 The fix was included in VAXACRT02_070 and ALPACRT02_070 ECO kits and
 appears in all subsequent ECO kits for OpenVMS V7.0.

 From VAXACRT05_070 Release Notes:

   Problems addressed in VAXACRT02_070 kit

      o  The DEC C Runtime Library does  not  properly  handle  all  rms
         error  codes  that  have  secondary  values returned in the stv
         fields.  For example, after a call to the open function  fails,
         the  perror function reports the error 'ACP create failed', but
         does  not  indicate  the  specific  reason  available  in   the
         secondary RMS status.

 Do you need a fix for a VMS version prior to V7.0?

 Boris
2138.2Sorry...DRAGNS::SAUNDERSMon Apr 07 1997 13:1821
Sorry for the lack of version info. This was running on version V6.2 of OpenVMS
VAX. I don't know about CRTL patches.

Since reading your response, I've been playing with perror on a V6.1 and a V7.1
system. I'm still working to find an error that would reproduce an RMS$_ACC
error, but in the mean time, I've seen that on OpenVMS VAX V7.1 you're
translating RMS$_CRE/SS$_BADIRECTORY into "i/o error". That's not the problem my
customer is having, but it's not a very good translation, either.

Do you have a list of the STV values for RMS$_ACC and the corresponding error
text as of your fix? This customer is starting to bristle, and could use the
reassurance that the log file will give the answer in the future.


For the present, I learned that your fix will only help my test program - the
actual code shipped with the product is built with VAX C :-(  I'll be asking for
clues over in that conference next.

Thanks,
John Saunders
DECdns Engineering
2138.3how to get RMS$_ACC status and other things - rep. to .2TAVENG::BORISBoris Gubenko, ISETue Apr 08 1997 12:12155
> 
> Since reading your response, I've been playing with perror on a V6.1 and a V7.1
> system. I'm still working to find an error that would reproduce an RMS$_ACC
> error, but in the mean time, I've seen that on OpenVMS VAX V7.1 you're
> translating RMS$_CRE/SS$_BADIRECTORY into "i/o error". That's not the problem my
> customer is having, but it's not a very good translation, either.
> 

  I managed to cause RMS$_ACC error status specifying unknown node in the file
  specification for fopen() function - see example below.

  You cannot expect, that perror() will map every VMS condition value to a
  separate errno value with its own message explaining the error. I have no
  idea how many condition values exist on VMS (I think, only <ssdef.h> contains
  more than 400 condition values) but the total number of errno values, as can
  be seen from the <errno.h> header, is only 86:

#ifndef __HIDE_FORBIDDEN_NAMES
#define __ERRNO_MAX     86     /* MUST equal largest errno value        */
#define EVMSERR         65535  /* error for non-translatable VMS errors */
#endif

  Due to its ambiguity, the perror() function is not the best way to analyze
  a VMS condition value. For example, the following VMS status codes are mapped
  to the same EIO errno having the "i/o error" message:

    RMS$_IFI,		EIO,
    RMS$_ISI,		EIO,	
    RMS$_CRE,		EIO,		
    RMS$_ACC,		EIO,
    RMS$_DAC,		EIO,
    RMS$_ENT,		EIO,
    RMS$_EXT,		EIO,
    RMS$_FND,		EIO,
    RMS$_MKD,		EIO,
    RMS$_DPE,		EIO,
    RMS$_SPL,		EIO,
    RMS$_RUF,		EIO,
    RMS$_WRTJNL_AIJ,	EIO,
    RMS$_WRTJNL_BIJ,	EIO,
    RMS$_WRTJNL_ATJ,	EIO,
    RMS$_WRTJNL_RUJ,	EIO,
    RMS$_RRF,		EIO,
    RMS$_DDTM_ERR,	EIO,
    RMS$_ATR,		EIO,
    RMS$_ATW,		EIO,
    RMS$_CCF,		EIO,
    RMS$_CDA,		EIO,
    RMS$_CHN,		EIO,
    RMS$_RER,		EIO,
    RMS$_RMV,		EIO,
    RMS$_RPL,		EIO,
    RMS$_SYS,		EIO,
    RMS$_WER,		EIO,
    RMS$_WPL,		EIO,
    RMS$_IFA,		EIO,
    RMS$_WBE,		EIO,
    RMS$_ENQ,		EIO,
    RMS$_NETFAIL,	EIO,
    RMS$_SUPPORT,	EIO,
    RMS$_CRMP,		EIO,
    RMS$_DTFCFGFIL,	EIO,
    RMS$_REENT,		EIO,
    RMS$_ACC_RUJ,	EIO,
    RMS$_TMR,		EIO,
    RMS$_ACC_AIJ,	EIO,
    RMS$_ACC_BIJ,	EIO,
    RMS$_ACC_ATJ,	EIO,
    RMS$_DTFREGFIL,	EIO,
    RMS$_JNLNOTAUTH,	EIO,		

  All possible errno values and their associated messages can be found in
  Table 4-2 in the DEC C RTL Reference Manual.

  So, regardless of the fix done to OpenVMS V7.1, perror() will always return
  an "i/o error" message for RMS$_ACC status.

  As stated in Section 4.1 in the Manual, the OpenVMS condition value is
  available in the vaxc$errno variable. The message associated with OpenVMS
  condition value can be obtained through strerror() function if errno argument
  is set to EVMSERR.

> 
> Do you have a list of the STV values for RMS$_ACC and the corresponding error
> text as of your fix? This customer is starting to bristle, and could use the
> reassurance that the log file will give the answer in the future.

  I don't have the list. The log file will give the answer only if strerror()
  will be used instead of perror() and the fix done for OpenVMS V7.1 will be
  ECOed for V6.2. Currently it is ECOed for V7.0 only.

  The fix done to OpenVMS V7.1 is that the vaxc$errno is set to the FAB$L_STV
  status. Prior to V7.1, the errno was set to EVMSERR and vaxc$errno was set
  to FAB$L_STS status. The example below illustrates the difference between the
  OpenVMS V6.2 and V7.1. As you can see from the example, on V7.1 one does not
  need the "err" callback function to get a real status - this status can be
  obtained via the call to strerror().

> 
> For the present, I learned that your fix will only help my test program - the
> actual code shipped with the product is built with VAX C :-(  I'll be asking for
> clues over in that conference next.
> 

  Even though the product is compiled using VAX C, and, I guess, is linked
  against VAX C RTL, probably, you can relink the product to use the DEC C
  RTL instead. This will let you take advantage of the new features of the DEC
  C RTL and bug fixes. See section 1.3 RTL Linking Options on VAX Systems in
  the Manual.

  Boris

$ cc/version/noobj _nl0:
DEC C V5.0-003 on OpenVMS Alpha V6.2-1H1
$ run x
acp file access failed
remote node is unknown
fopen: non-translatable vms error code: 0x1C002
%rms-e-acc, acp file access failed
acp file access failed

$ cc/version/noobj _nl0:
DEC C V5.2-003 on OpenVMS Alpha V7.1
$ run x
acp file access failed
remote node is unknown
fopen: i/o error
remote node is unknown

X.C
===

#include <errno.h>
#include <stdio.h>
#include <string.h>

#include <rms.h>

static int err_callback(int *tmp, struct FAB *fab, struct RAB *rab)
{
  puts(strerror(EVMSERR,fab->fab$l_sts));
  puts(strerror(EVMSERR,fab->fab$l_stv));

  return -1;
}

main()
{
  int i;

  if ( !fopen("abcdef::mba1:", "r", "err", err_callback, &i) ) {
    perror("fopen");
    puts(strerror(EVMSERR));
  }
}
2138.4SPECXN::DERAMODan D&#039;EramoTue Apr 08 1997 12:424
        With VAX C, you can get access to the FAB and RAB via an
        undocumented function (TURRIS::VAXC reply 3887.1).
        
        Dan
2138.5This Is Not GoodDRAGNS::SAUNDERSJohn Saunders, DECdns Engineering, DTN 226-5173Tue Apr 08 1997 14:5843
    Boris, you said:
      
    "You cannot expect, that perror() will map every VMS condition value to a
    separate errno value with its own message explaining the error."
    
    I have no expectation that perror will do this. What I expected is that,
    for every VMS error condition which is reasonably mapped to an errno
    value, that the mapping is performed. I did not previously consider it
    reasonable to map RMS$_ACC to "i/o error", but I'm willing to concede
    that others might argue that this is reasonable.
    
    Users of OpenVMS expect better diagnostics than "i/o error". The
    previous functionality at least used to output "%RMS-E-ACC", so that we
    used to have some kind of idea of what was going on, without having to
    use radically-different code between OpenVMS, Digital UNIX, and Ultrix.
    I had hoped that future versions of the RTL would only improve upon
    this functionality by outputting both the STS and STV values.
    
    Now you tell me that we're back to the Least Common Denominator. I'm
    hearing that instead of extending perror to output the additional
    information OpenVMS can provide, the decision was made to lose
    information, in fact to hide it from the customer, the field, and
    Engineering. I think I'm hearing that in order to get the functionality
    we used to have, we have to modify all the open() calls in DECdns to
    include an "err" routine, then test and ship a new ECO!
    
    And to compile it with a new compiler besides!
    
    If I'm reading this wrong, please let me know. Right now, I'm not very
    pleased, and neither will the customer be.
    
    
    re: .4:
    
    If you are referring to the _fstat function, my readings in the VAXC
    conference suggest that it takes a file descriptor as its first
    argument. I need to get the error status in the case that an open
    fails. In that case, I have no file descriptor to pass to _fstat.
    
    
    Thanks,
    John Saunders
    DECdns Engineering
2138.6SPECXN::DERAMODan D&#039;EramoTue Apr 08 1997 15:4115
	re .5
        
>    re: .4:
>    
>    If you are referring to the _fstat function, my readings in the VAXC
        
        Yes...
        
>    conference suggest that it takes a file descriptor as its first
>    argument. I need to get the error status in the case that an open
>    fails. In that case, I have no file descriptor to pass to _fstat.
        
        ... oops ... _fstat won't help for that.
        
        Dan
2138.7We will investigate enhancementsTLE::D_SMITHDuane Smith -- DEC C RTLTue Apr 08 1997 20:0263
John,

  First off, thank you for the problem report.  While our hands are tied
  in some respects, we may be able to work up a design to provide more
  information from both the strerror() and perror() routines.

  I don't have the ANSI specification in front of me, but it specifies
  exactly what the perror() routine is expected to do and how the string
  displayed by perror() relate to strerror().

     perror(s) == fprintf(stderr, "%s: %d", s, strerror(errno))


  In the DEC C RTL, we have both errno and vaxc$errno.  In fact, perror can
  be thought of as

     perror(s) == fprintf(stderr, "%s: %d", s, strerror(errno, vaxc$errno))


  The problem is that the value of vaxc$errno is defined only when errno
  is equivalent to EVMSERR.  The strerror() function will only examine the
  second argument if the first is EVMSERR.

  In the example of opening a file with an invalid node name, the RMS status
  is RMS$_ACC with a secondary status of SS$_NOSUCHNODE.  The DEC C RTL 
  converts RMS$_ACC into an errno value of EIO (I/O Error).  The value of
  vaxc$errno is set to SS$_NOSUCHNODE.

  Another ANSI rule that comes into play is that we can only touch errno
  if an error occurs during the specific call.  We are not permitted to 
  ever clear errno.  ANSI makes no such rules about vaxc$errno, since that
  is a DEC C extension.

  In order to make improvements in this area, I imagine that we will need 
  to change the current design to store

      errno        -- the c translation of the error
      vaxc$errno   -- the actual error which occured
      vaxc$errno2  -- the secondary status if vaxc$errno has one

  The value of vaxc$errno would be RMS$_ACC in this example while the value
  of vaxc$errno2 would be SYS$_NOSUCHNODE.  When an error occurs, errno is
  established.  The vaxc$errno and vaxc$errno2 would have to kept consistent
  with changes made to errno.  If errno was set to an error such as EINVAL
  (invalid argument), then both vaxc$errno and vaxc$errno2 would be cleared.
  If errno was set to a value based on a single error status, the vaxc$errno2
  would be cleared.  Only in the case of a system error which has secondary
  information would all three cells contain a value.

  My project will investigate what we can do to improve the usability of 
  perror and strerror while retaining upward compatibility for those 
  applications which rely on the values of vaxc$errno.  Based on our findings,
  these changes may or may not be ECOed onto a platform.  Have you ever 
  issued an ECO kit which broke products such as Oracle?  It's not a pleasant
  experience.

  Also, please do not assume that any changes will be done to the VAX C RTL 
  based on this note.  It would require at least a priority 1 or a high 2 
  IPMT case to have changes made to the VAXCRTL[G].EXE images.


Duane Smith
OpenVMS DEC C Runtime Library
2138.7we will investigateTLE::D_SMITHDuane Smith -- DEC C RTLWed Apr 09 1997 08:2563
John,

  First off, thank you for the problem report.  While our hands are tied
  in some respects, we may be able to work up a design to provide more
  information from both the strerror() and perror() routines.

  I don't have the ANSI specification in front of me, but it specifies
  exactly what the perror() routine is expected to do and how the string
  displayed by perror() relate to strerror().

     perror(s) == fprintf(stderr, "%s: %s", s, strerror(errno))


  In the DEC C RTL, we have both errno and vaxc$errno.  In fact, perror can
  be thought of as

     perror(s) == fprintf(stderr, "%s: %s", s, strerror(errno, vaxc$errno))


  The problem is that the value of vaxc$errno is defined only when errno
  is equivalent to EVMSERR.  The strerror() function will only examine the
  second argument if the first is EVMSERR.

  In the example of opening a file with an invalid node name, the RMS status
  is RMS$_ACC with a secondary status of SS$_NOSUCHNODE.  The DEC C RTL 
  converts RMS$_ACC into an errno value of EIO (I/O Error).  The value of
  vaxc$errno is set to SS$_NOSUCHNODE.

  Another ANSI rule that comes into play is that we can only touch errno
  if an error occurs during the specific call.  We are not permitted to 
  ever clear errno.  ANSI makes no such rules about vaxc$errno, since that
  is a DEC C extension.

  In order to make improvements in this area, I imagine that we will need 
  to change the current design to store

      errno        -- the c translation of the error
      vaxc$errno   -- the actual error which occured
      vaxc$errno2  -- the secondary status if vaxc$errno has one

  The value of vaxc$errno would be RMS$_ACC in this example while the value
  of vaxc$errno2 would be SYS$_NOSUCHNODE.  When an error occurs, errno is
  established.  The vaxc$errno and vaxc$errno2 would have to kept consistent
  with changes made to errno.  If errno was set to an error such as EINVAL
  (invalid argument), then both vaxc$errno and vaxc$errno2 would be cleared.
  If errno was set to a value based on a single error status, the vaxc$errno2
  would be cleared.  Only in the case of a system error which has secondary
  information would all three cells contain a value.

  My project will investigate what we can do to improve the usability of 
  perror and strerror while retaining upward compatibility for those 
  applications which rely on the values of vaxc$errno.  Based on our findings,
  these changes may or may not be ECOed onto a platform.  Have you ever 
  issued an ECO kit which broke products such as Oracle?  It's not a pleasant
  experience.

  Also, please do not assume that any changes will be done to the VAX C RTL 
  based on this note.  It would require at least a priority 1 or a high 2 
  IPMT case to have changes made to the VAXCRTL[G].EXE images.


Duane Smith
OpenVMS DEC C Runtime Library
2138.8Can we work within the system?WIBBIN::NOYCEPulling weeds, pickin&#039; stonesWed Apr 09 1997 09:549
Would it be reasonable to translate RMS$_ACC into EVMSERR
instead of EIO, at least in cases where we see that the STV
provides additional information?  Would it be reasonable
to copy the STV to vaxc$errno instead of copying the less
informative RMS$_ACC?  Are there any real programs that
would suffer from this kind of incompatible change?

This would let you use the existing framework, and make changes
only in how open() maps its RMS errors.
2138.9DRAGNS::SAUNDERSJohn Saunders, DECdns Engineering, DTN 226-5173Wed Apr 09 1997 12:2749
Thanks for the responses. If I understand you, vaxc$errno is documented to be
defined only when errno is EVMSERR. If this is the case, then you do not have to
change vaxc$errno (and vaxc$errno2) whenever errno changes, but only when it is
set to EVMSERR. That is, the only code that should have to touch
vaxc$errno/errno2 is code which sets errno to EVMSERR.

If this is so, vaxc$errno2 should be defined to be set only when errno is
EVMSERR and vaxc$errno contains an RMS error. In that case, it would be defined
to be the FAB$L_STV or RAB$L_STV value, depending on which sort of operation
failed.

For consistancy then, strerror should be extended to have an optional third
argument, which is only examined when errno is EVMSERR and vaxc$errno is an RMS
error. The third argument would be the STV value. The pair of
vaxc$errno,vaxc$errno2 could then be supplied to the SYS$PUTMSG call that writes
the string returned by strerror (don't forget to grow that string!).

perror could then be equivalent to:

perror(s) == fprintf (stderr, "%s: %s", s,
			strerror (errno, vaxc$errno, vaxc$errno2));

This should be OK by ANSI and any test suite, at least for any ANSI-defined
errno values.

Of course, you should review the mappings of VMS errors to errno values: EIO was
a stretch for something to map to, and in this case caused valuable information
to be lost.


We don't expect any changes to ever be made to VAXCRTL, by the way. We'll
eventually be converting to DECC. My hope is that when we do, some ECO will have
been issued on the platforms we support that will allow us to get useful
information from the Field without having to recode all our opens and creat's.


Thanks,
John Saunders
DECdns Engineering


P.S. I prefer vaxc$rms_stv or something. It's not an "errno".

P.P.S. If we've got to recode, I'll probably try macros called "open" and
"creat" that call our own function, which will call the real open and creat with
the three additional parameters ["err", file_open_rtn, x]. file_open_rtn would
then have to store STS and STV. We'd then have to have our own perror and
strerror that would use the STS and STV. This would sure be cleaner if you did
it rather than I...
2138.10SPECXN::DERAMODan D&#039;EramoWed Apr 09 1997 13:4051
>  I don't have the ANSI specification in front of me, but it specifies
>  exactly what the perror() routine is expected to do and how the string
>  displayed by perror() relate to strerror().
>
>     perror(s) == fprintf(stderr, "%s: %s", s, strerror(errno))

        My copy is handy. :-)  The wording translates more like
        
        	if ((s == NULL) || (*s == '\0'))
        	    fprintf(stderr, "%s\n", strerror(errno));
        	else
        	    fprintf(stderr, "%s: %s\n", s, strerror(errno));

        which doesn't change anything that was said afterward.
        I just like to peek at the standard. :-)
        
>  Another ANSI rule that comes into play is that we can only touch errno
>  if an error occurs during the specific call.  We are not permitted to 
>  ever clear errno.  ANSI makes no such rules about vaxc$errno, since that
>  is a DEC C extension.
        
        Unless it has changed from the X3.159-1989 document, the rule
        is
        
        	The value of errno is zero at program startup, but is
        	never set to zero by any library function.  The value
        	of errno may be set to nonzero by a library function
        	call whether or not there is an error, provided the
        	use of errno is not documented in the description of
        	the function in the standard.
        
        So for example the use of errno is not documented in the
        description of the fopen() function in the standard, so even
        successful fopen() calls can modify errno (although they
        cannot change a nonzero errno back to zero).
        
        As long as users only check errno after a failed call (for
        example, only check error if fopen returned a null pointer)
        they won't trip over this.
        
        On OpenVMS, the call fopen(filename, "w") checks if there is
        an existing version of `filename' so that it can inherit its
        attributes (record format, record attribute, etc.).  If there
        was no existing version, the result was setting errno to
        ENOENT, even though the fopen did successfully create the new
        file and returned a non-null pointer.  It is compliant to
        change errno to ENOENT on a successful fopen() call, but
        people complained anyway so we changed it to restore the old
        value of errno in this case.  To the standard...and beyond! :-)
        
        Dan
2138.11DRAGNS::SAUNDERSJohn Saunders, DECdns Engineering, (508) 275-5424Fri May 16 1997 13:0018
We finally found out what the problem is.

Someone suggested that I should try to find out whether the problem is in the C
RTL or whether it's in RMS. So I wrote the equivalent RMS code to do the open,
printing out both the STS and STV.

This showed that our problem is BYTLM. The customer has a low PQL_MBYTLM setting.

Increasing that setting fixes the problem at our test site, and we hope it fixes
the problem in the field!

Thanks for all the suggestions,
John Saunders
DECdns Engineering

P.S. This just makes my earlier point: if  we'd known immediately that the
problem which prevented the open from working was "no BYTLM", then we'd have
been able to solve it about a month ago.