We in the DEC C RTL engineering team need opinions on what to
do with the C exit() function.
The problem we're trying to solve is two-fold:
1. Today, the parameter of exit() is interpetted as a VMS condition
code, which frequently causes spurious messages to be displayed.
For example, exit(12) results in:
$ run b
%SYSTEM-F-ACCVIO, access violation, reason mask=00, virtual address=0000000C, PC
=00000012, PS=00000003
$
even though the program did not really accvio.
2. The new waitpid function is limited to an 8-bit exit value.
Part of the spec for exit (from ANSI C, in fact) is that the
implementor must define macros EXIT_SUCCESS and EXIT_FAILURE.
Today, EXIT_SUCCESS is 0 and EXIT_FAILURE is the VMS condition
value 0x10000002. Most unix implementations define EXIT_FAILURE to
be 1.
What we've done to date for OpenVMS V7.0 is to implement 2 versions
of exit(). The old exit accepts a VMS condition code. The new
exit accepts a number between 0 and 255 -- actually, it silently
truncates the number into the range of 0 to 255. Through header
file magic and conditional compilation, you can chose which exit
you want. In the current field test, the default is the new,
more standards comforming version. Having the out of the box
behavior align with standards is the general approach we've take
for other changes in DEC C V5.2.
What we found that concerns us is old code that calls exit(SS$_NORMAL);
SS$_NORMAL is the value 1, and we were planning to change EXIT_FAILURE
to be 1. The concern is that the new (default) exit will treat
exit(1) as the failure case, not the success case.
We've thought of a range of options, none of which are obviously
the simple, correct answer. I'm looking for feedback, generally
around 2 questions:
1. Is changing the default behavior for programs that recompile acceptable?
2. Do you rely on exit() taking a VMS condition value?
--
Ken Cowan, ZK2-3/Q8 co...@rtl.enet.dec.com
Digital Equipment Corporation decwrl!rtl!cowan
110 Spit Brook Rd,
Nashua, NH 03062
Hmmm. In that case, why go to the trouble of 2 versions of exit()? Why not
just use the same conditional compilation and header file magic to
conditionally include the preprocessor directive:
#define exit SYS$EXIT
=1. Is changing the default behavior for programs that recompile acceptable?
I'd rather have the default to be to use the old behavior.
=2. Do you rely on exit() taking a VMS condition value?
I generally use SYS$EXIT, myself, in situations where I'm exiting with a VMS
condition value.
--------------------------------------------------------------------------------
Carl J Lydick | INTERnet: CA...@SOL1.GPS.CALTECH.EDU | NSI/HEPnet: SOL1::CARL
Disclaimer: Hey, I understand VAXen and VMS. That's what I get paid for. My
understanding of astronomy is purely at the amateur level (or below). So
unless what I'm saying is directly related to VAX/VMS, don't hold me or my
organization responsible for it. If it IS related to VAX/VMS, you can try to
hold me responsible for it, but my organization had nothing to do with it.
It's not clear to me what you're really saying about what gets
returned to the operating system when a program exits. It looks
like you're saying that 1 will be returned on an error. So what
happens if I'm trying to catch an error with $on error then ...??
What happens on success - 0? But this code is not a VMS success
code. So, if I'm trying to write a DCL procedure that calls
various images which may or may not be written in C and may or
may not be using the new "standard", I basically have to give up
on the standard VMS success/info, warning/error/severe_error
scheme. Instead I have to set noon and know the status codes
returned by each image and check them after each image.
If I've understood what you're saying, it sounds like a giant
step backwards. Just because it's unix does not make it right,
better, or a standard!
- Ed
/----------------------------------------------------------------------\
| Edward J. Groth | Phone: 609-258-4361 Fax: 609-258-6853 |
| Physics Dept., Jadwin Hall | URL: http://pupgg.princeton.edu/~groth/ |
| Princeton University | SPAN/HEPNET: PUPGG::GROTH=44117::GROTH |
| Princeton, NJ 08544 | Internet: gr...@pupgg.princeton.edu |
\----------------------------------------------------------------------/
Mike
I rely on the VMS condition values being available to me. I don't mind too
much if I have to use a different exit service to get non-ANSI results
(if I recompile I might have to modify the source a little - but I don't
recompile without a reason - so I'm mucking with the source already) but
I do want to be able to get them. If I can't get the values I expect then
I lose the ability to use $STATUS in a standard manor for all image exists.
Image exit status must be standard and easilly set from within the program
and must not become source language dependant.
+---------------------------------------------------------------------------+
| Brian R Cuttler | bitnet: sysbrc@albnyvms |
| VMS System Manager | internet: sys...@albnyvms.albany.edu |
| State Univ of NY at Albany | phone: 518-442-3906 fax: 518-442-3697 |
+---------------------------------------------------------------------------+
In article <434b0s$k...@nntpd.lkg.dec.com>, co...@btgmax.zko.dec.com (Ken Cowan) writes:
>
>
>We in the DEC C RTL engineering team need opinions on what to
>do with the C exit() function.
>
>The problem we're trying to solve is two-fold:
>
>1. Today, the parameter of exit() is interpetted as a VMS condition
> code, which frequently causes spurious messages to be displayed.
> For example, exit(12) results in:
>
>$ run b
>%SYSTEM-F-ACCVIO, access violation, reason mask=00, virtual address=0000000C, PC
>=00000012, PS=00000003
>$
>
> even though the program did not really accvio.
>
>2. The new waitpid function is limited to an 8-bit exit value.
>
>Part of the spec for exit (from ANSI C, in fact) is that the
>implementor must define macros EXIT_SUCCESS and EXIT_FAILURE.
>Today, EXIT_SUCCESS is 0 and EXIT_FAILURE is the VMS condition
>value 0x10000002. Most unix implementations define EXIT_FAILURE to
>be 1.
>
>What we've done to date for OpenVMS V7.0 is to implement 2 versions
>of exit(). The old exit accepts a VMS condition code. The new
>exit accepts a number between 0 and 255 -- actually, it silently
>truncates the number into the range of 0 to 255. Through header
>file magic and conditional compilation, you can chose which exit
>you want. In the current field test, the default is the new,
>more standards comforming version. Having the out of the box
>behavior align with standards is the general approach we've take
>for other changes in DEC C V5.2.
>
>What we found that concerns us is old code that calls exit(SS$_NORMAL);
>SS$_NORMAL is the value 1, and we were planning to change EXIT_FAILURE
>to be 1. The concern is that the new (default) exit will treat
>exit(1) as the failure case, not the success case.
>
>We've thought of a range of options, none of which are obviously
>the simple, correct answer. I'm looking for feedback, generally
>around 2 questions:
>
>1. Is changing the default behavior for programs that recompile acceptable?
>
>2. Do you rely on exit() taking a VMS condition value?
>
I suspect that there is some confusion here. I don't think that DEC is
saying that exit(0) will result in 0 being the termination status from
the program. (Can we get a clarification from DEC here?)
I think that they are saying that exit(0) will cause the program to
return SS$_NORMAL and exit(1) will cause the program to return an error
status, probably some new status defined for just this case.
(What will exit(2) return?)
The problem is that exit(SS$_NORMAL) is exit(1), which would actually
result in an error being returned, which is not what is intended.
Personally, I consider exit(SS$_NORMAL) to be a coding error, as exit(0)
is standard and is documented as returning SS$_NORMAL as the image's
termination status.
However, in the interests of backwards compatibility, I suggest:
VAXCRTL should preserve the old behavior.
DECC$SHR should look at the main image's header to find the version of the
RTL which the image was linked against. This should determine whether the
new or the old behavior is used.
An alternative to exit() should be provided, perhaps vms$exit(), which
allows an explicit condition value to be returned as the image's
termination status.
------------------------------------------------------------------------
Chris Scheers, Applied Synergy, Inc.
817-237-3360 (Voice) 817-237-3074 (Fax) Internet: a...@airmail.net
ANSI 4.10.4.3 documents only three parmeters to exit(): 0,
EXIT_SUCCESS and EXIT_FAILURE. While common Unix practice it to use
exit(1) for failure, this is implementation defined behavor and is
less portable than exit(EXIT_FAILURE).
So why not do the following
exit(0):
exit(EXIT_SUCCESS): successful termination
exit(SS$_NORMAL): normal termination
exit(EXIT_FAILURE): unsuccessful termination
That is, make EXIT_FAILURE something other than 0 or SS$_NORMAL (like
2 or 255).
Sure, Unix programs that call exit(1) won't work right, but that
easily be fixed by changing them to be exit(EXIT_FAILURE).
Dan
--
--------------------- message is author's opinion only --------------------
J. Daniel Smith <Da...@bristol.com> http://www.bristol.com/~dan
Bristol Technology Inc. +1 203 438 6969, 438-5013 (FAX)
Ridgefield, Connecticut (USA) {info,jobs}@bristol.com
> The problem we're trying to solve is two-fold:
>
> 1. Today, the parameter of exit() is interpetted as a VMS condition
> code, which frequently causes spurious messages to be displayed.
> For example, exit(12) results in:
> $ run b
> %SYSTEM-F-ACCVIO, access violation, reason mask=00, [...]
Any program which uses `exit(12);' is in error unless it meant to
return SS$_ACCVIO. That was true before the ANSI Standard and is still
true after the adoption of the ANSI Standard. What would such a program
expect to accomplish?
> 2. The new waitpid function is limited to an 8-bit exit value.
The VMS POSIX implementation of `waitpid()' does not appear to have
that limitation (based on its online help; I've never used it). Why
implement something that's incompatible with an existing standard? ;-)
Perhaps you'd care to elaborate, perhaps by explaining what it's
useful for and when it might actually be used? Maybe that can be solved
by introducing `waitexit()' for programs that arbitrarily need to return
8 bits, leaving `exit()' alone.
> [...] In the current field test, the default is the new,
> more standards comforming version. Having the out of the box
> behavior align with standards is the general approach we've take
> for other changes in DEC C V5.2.
How in the world does the proposed new behavior qualify as "more
standards conforming"??? The standard specifically defines the behavior
for three values (EXIT_SUCCESS, EXIT_FAILURE, and 0) and states that
other values are implementation defined. Surely you can document DEC C
as using native VMS condition values for anything other than those three.
That will be 100% standard conforming, hence any attempt to be "more
conforming" is clearly futile...
> 1. Is changing the default behavior for programs that recompile acceptable?
That will break existing programs, a cardinal sin according to the
tenets of the original ANSI standardization process (as opposed to the
apparent learnings of the new standard committee), and also according
to past Digital history.
You know there will bug reports and complaints from users who
recompile without having read the release notes. "Read the documentation"
is an acceptible response to whoever actually did the installation, but
not very nice to umpteen end users who may not have easy access to it...
> 2. Do you rely on exit() taking a VMS condition value?
Yes, in native VMS code. Portable code typically defines `exit' as
macro pointing to `vms_exit' or something of the sort, and `vms_exit'
simply maps 0 to EXIT_SUCCESS and non-0 to EXIT_FAILURE and then calls
exit(). Alternatively, it maps to SS$_NORMAL and SS$_ABORT, then calls
sys$exit(), bypassing the C RTL altogether. Two distinct values, for
success and failure, are adequate for portable code. Trying to return
other values is inherently non-portable, and I'd hate to see DECC$SHR
start encouraging that.
Pat Rankin, ran...@eql.caltech.edu
You're right, I was not clear. With both implementations of exit,
DCL command procedures work fine. I'll describe today's FT software:
Both implementations define EXIT_SUCCESS to be 0. [VAX C and DEC C
on OpenVMS always have.] 0 gets mapped into a call to
sys$exit(SS$_NORMAL), which is a success status.
The old implementation defines EXIT_FAILURE to be 0x10000002
which is a status of "%NONAME-E-NOMSG, Message number 00000002"
but with the inhibit message bit set. ON ERROR is triggered
(since the severity is 2).
The old implementation treats all values beside 0 as a VMS condition
code. ie. exit(8) is a warning, exit(9) is success, exit(10)
is error, exit(11) is informational, exit(12) is severe error.
The new implementation defines EXIT_FAILURE to be 1 and maps
this into a call to sys$exit( C$_EXIT1 & ~STS$M_SEVERITY | STS$K_ERROR)
i.e. it's a C RTL facility code with the severity set to 2.
ON ERROR is triggered for that case.
For numbers in the range 2..255, the new implementation maps them
into C$_EXITn which is a code with the severity of success.
For numbers above 255, the new impmentation uses the value modulo 255.
And, you won't have to change your code if you rely on the old behavior.
With our current FT software, if you recompile and you want the old
behavior, you have to recompile /DEFINE=_VMS_V6_SOURCE, or add
#define _VMS_V6_SOURCE 1 to the top of your source file. You also
are welcome to change the source to call sys$exit directly -- but
I clearly cannot force you to change source to upgrade your compiler.
People would have my head on platter if I even suggested such a thing!
Note that I did say "if you recompile". We're talking about the default
code path through a #if condition in a header file. If you don't
recompile, your old .exe still gets the old decc$exit routine which
is unchanged.
Hope this makes is more clear. I am listening to all the comments
here and through mail. Thanks for the inputs so far!
I presume functions registered with atexit() are stored internal to
the C RTL for use by exit() and thus are not available to SYS$EXIT.
>You also
>are welcome to change the source to call sys$exit directly -- but
>I clearly cannot force you to change source to upgrade your compiler.
>People would have my head on platter if I even suggested such a thing!
okay, it really is ken. that first article had me wondering ;-)
but i don't understand why you're bothering with this feature,
since the point of exit(anything) is to pass a number to the shell,
and VMS is by definition incapable of accepting "a" number without
barfing half the time. since it has nothing to do with C or the RTL,
i'm not sure what you're going to accomplish. under unix you can
givetest
if (($? >= 90))
then grade=A
but under VMS, regardless of any RTL magics, you can't
$ run givetest.exe
$ if f$integer($status) .ge. 90 then grade := A
unless you think people will
$ if (f$integer($status) .and. 255) .ge. 90 then grade := A
hopefully i'm missing something?
ok
dpm
--
David P. Murphy mailto:mur...@connor.datametrics.com (work)
systems programmer mailto:d...@access.digex.net (personal)
http://www.access.digex.net/~dpm
COGITO ERGO DISCLAIMUM ftp://ftp.digex.net/pub/access/dpm
While I realize that this can bite programs written with the Unix
assumption that exit codes don't have any intrinsic significance to
the shell, I don't think treating the parameter passed to exit as a
VMS status value is a problem. Offhand, I can think of three ways to
deal with the parameter passed to exit():
- treat it as a status value, since that's what the CLI is going to
do. waitpid() may lop off the top 24 bits, meaning that much of the
specific message information is lost, but the CLI is still going to
treat whatever it sees as a status value, and the programmer has to
expect that and respond appropriately
- ignore the parameter, and pass a single status value back to
the CLI, regardless of the value with which exit() is called
(or, alternatively, return one of two status values, indicating
"success" or "failure" (SS$_NORMAL and SS$_ABORT, for example)
based on some simple test of the parameter passed to exit()
(odd or even, zero or non-zero, etc)).
- adopt strategy two, but store the value of the parameter passed
to exit() as a DCL symbol (say C$STATUS), so that DCL procedures
which are aware that a C image has just been called can test
that symbol to determine the "exit code" of the image.
Of these options, I'd prefer the first, since it conforms best to a
uniform property of the rest of VMS. I'm all for emulating Unix
behavior for the sake of portability, but in the end, the world
outside the C program is VMS, and I'd hate to cripple the world
(in the sense that it has to deal differently with C programs,
whether written with Unix in mind or not) in order to accomodate
the program.
> 2. The new waitpid function is limited to an 8-bit exit value.
Is this an ANSI requirement? I realize that many Unix waitpid()s
behave this way, but there're 24 bits left in the int used for
the process' exit value after the low-order 8 are used to encode
the method of the process' demise. Would it be possible for
*statusp to contain (child_termination_status << 8) | signal_code?
That'd still conform to the standard definition (low-order 8 bits
encode the method of the process' demise; if the process called
exit(), the next 8 bits are the low-order 8 bits of the value
passed to exit()), and provide 16 more bits of information about
the process' exit status. While this still lops of some
important parts of a VMS status value, it's nicer to know that
I'm going to lose facility and options, but keep severity and
14 of the 16 ident bits.
> Part of the spec for exit (from ANSI C, in fact) is that the
> implementor must define macros EXIT_SUCCESS and EXIT_FAILURE.
> Today, EXIT_SUCCESS is 0 and EXIT_FAILURE is the VMS condition
> value 0x10000002. Most unix implementations define EXIT_FAILURE to
> be 1.
>
> What we've done to date for OpenVMS V7.0 is to implement 2 versions
> of exit(). The old exit accepts a VMS condition code. The new
> exit accepts a number between 0 and 255 -- actually, it silently
> truncates the number into the range of 0 to 255. Through header
> file magic and conditional compilation, you can chose which exit
> you want. In the current field test, the default is the new,
> more standards comforming version. Having the out of the box
> behavior align with standards is the general approach we've take
> for other changes in DEC C V5.2.
Hmm. That'd certainly break code I'm familiar with, which returns
status values chosen from ssdef.h, libdef.h, etc., so that the
corresponding message approximately describes what the program
encountered.
Is there a reason to restrict the value passed to exit to 8 bits? It
takes an int argument, and nothing I've seen other than waitpid() says
anything about only the low-order 8 bits being significant. (Of
course, I'm also not fluent in the details of the ANSI standard.)
What does the new exit() do with the byte that it uses? Does it pass
it out to the CLI or calling process, where it'll be interpreted as a
VMS condition value, or does exit() map the byte into one of a series
of VMS condition values to return as the image's exit status?
> What we found that concerns us is old code that calls exit(SS$_NORMAL);
> SS$_NORMAL is the value 1, and we were planning to change EXIT_FAILURE
> to be 1. The concern is that the new (default) exit will treat
> exit(1) as the failure case, not the success case.
Please don't do this. The value 1 means success all over the place in
VMS; it'd only confuse matters to make it mean failure for the exit()
routine in C, even if you're planning to have exit(1) actually return
some other status value to the CLI. Well-designed programs from
whatever source should use EXIT_FAILURE, and pick up VMS' definition
of this value. I don't think accomodating code which calls exit(1)
with a Unix mentality is worth changing the default behavior of exit
under VMS; I'd rather change the source code of a program I'm porting.
(I may regret that in the future, but it looks right now. :-))
> We've thought of a range of options, none of which are obviously
> the simple, correct answer. I'm looking for feedback, generally
> around 2 questions:
>
> 1. Is changing the default behavior for programs that recompile acceptable?
As a general principle, it might be, under some limited circumstances.
In this case, I think the loss of consistency with the rest of VMS
outweighs the gain in accomodation of code which comes with Unix
assumptions hard-coded in.
> 2. Do you rely on exit() taking a VMS condition value?
In many cases, yes -- I want to return some information to the CLI or
calling process about the state of the image which just terminated.
I realize that treating arguments to exit() as VMS condition values
maintains an environment different from Unix, and may make porting
Unix-based programs a bit more difficult. However, this is an area in
which VMS is significantly different from Unix, and I don't see a
single path that'll keep both happy. In this case, I'd rather see C
err on the side of being a 'native' language than a porting tool.
BTW, what does this change mean for return(value) from within main?
If I recall correctly, the ANSI standard says that this has to have
the same effect as calling exit(value). OTOH, I thought the VMS
calling standard said that the exit status of an image was the
return value from its top-level routine. If both of these are true
(unfortunately, I don't have the docs in front of me to look it up),
then the new behavior of exit() would create an apparent conflict.
(There's no real conflict, I guess, since the top-level routine of
a C program isn't the main() function in the source code, but people
do tend to think of main() in this way.)
Regards,
Charles Bailey bai...@genetics.upenn.edu
The problem we're trying to solve is two-fold:
1. Today, the parameter of exit() is interpetted as a VMS condition
code, which frequently causes spurious messages to be displayed.
For example, exit(12) results in:
$ run b
%SYSTEM-F-ACCVIO, access violation, reason mask=00, virtual
address=0000000C, PC=00000012, PS=00000003
$
even though the program did not really accvio.
2. The new waitpid function is limited to an 8-bit exit value.
Part of the spec for exit (from ANSI C, in fact) is that the
implementor must define macros EXIT_SUCCESS and EXIT_FAILURE. Today,
EXIT_SUCCESS is 0 and EXIT_FAILURE is the VMS condition value
0x10000002. Most unix implementations define EXIT_FAILURE to be 1.
There was an extended debate in the ANSI C committee on this topic. The
original proposal simply followed Unix: exit(0) means success, exit with any
non-zero argument means failure. (Actually, this is a lie anyway - though
you'll find it in most Unix books - since Unix systems only retain the bottom
7 or 8 bits - I forget which, it may vary from system to system. exit(256) on
is indistinguishable from exit(0) on any Unix system I know of.) It was
finally agree that the EXIT_SUCCESS and EXIT_FAILURE should be defined, and
that exit(0) must be interpreted as a successful completion. (EXIT_SUCCESS
does not have to be 0, according to the spec - there could in theory be two
different "successful exit" arguments.) The ANSI C spec leaves the interpre-
tation of exit(n) to implementations when n is not one of 0, EXIT_SUCCESS, or
EXIT_FAILURE (and really it doesn't even define what "success" and "failure"
mean).
What we've done to date for OpenVMS V7.0 is to implement 2 versions of
exit(). The old exit accepts a VMS condition code. The new exit
accepts a number between 0 and 255 -- actually, it silently truncates
the number into the range of 0 to 255.
Bug-for-bug compatibility with Unix! (It's a bug because the argument should
have been defined as an unsigned char - that's how it's treated!)
Through header file magic and
conditional compilation, you can chose which exit you want. In the
current field test, the default is the new, more standards comforming
version.
I know of no relevant standard that this conforms with.
Having the out of the box behavior align with standards is
the general approach we've take for other changes in DEC C V5.2.
What we found that concerns us is old code that calls
exit(SS$_NORMAL); SS$_NORMAL is the value 1, and we were planning to
change EXIT_FAILURE to be 1. The concern is that the new (default)
exit will treat exit(1) as the failure case, not the success case.
We've thought of a range of options, none of which are obviously the
simple, correct answer. I'm looking for feedback, generally around 2
questions:
1. Is changing the default behavior for programs that recompile
acceptable?
No. All of us who have, over the years, carefully written our code to conform
with the VAX C, then DEC C, specifications will not be happy to see it broken
in the interest of making porting of Unix code that *doesn't* bother to follow
the relevant standards and specifications. Hell, some of this code dates back
to DECUS C, which also did things the intelligent way!
2. Do you rely on exit() taking a VMS condition value?
I have many C programs that return SS$_NORMAL. In fact, I don't think I've
written any that call exit() with a numerical argument: The standard header
files I use, going back to DECUS C days, have always defined EXIT_SUCCESS
and EXIT_FAILURE macros - well, actually IO_SUCCESS and IO_ERROR in the older
code. The values are often 1 and 0 - in that order on VMS, in the reverse
order on Unix - but some code has the more VMS-specific values
(SS$_NORMAL|STS$M_INHIB_MSG) and SS$_ABORT.
In every port to VMS of a Unix C program I've ever done, one of the first
orders of business has been to change the exit() calls.
There really is no way to really emulate Unix behavior. There is at least one
fairly widely used Unix program that exit's with a count of errors as its
final status. (Just hope you don't have a makefile that checks this when you
have exactly 256 errors!) It's impossible to fit this program into the DCL
environment in any rational way.
There's perhaps no particular reason why the exit status *as returned to DCL*
should be the same as the exit status seen by wait(). The Unix final exit
status is actually 16 bits long, with only the top half or bottom half non-
zero: The bottom half is the value passed to exit(), the top half is the
signal number of an unhandled signal that caused the program to terminate.
Are you planning on supporting that, too?
In article <434b0s$k...@nntpd.lkg.dec.com>, co...@btgmax.zko.dec.com (Ken Cowan) writes:
>What we've done to date for OpenVMS V7.0 is to implement 2 versions
>of exit(). The old exit accepts a VMS condition code. The new
>exit accepts a number between 0 and 255 -- actually, it silently
>truncates the number into the range of 0 to 255. Through header
>file magic and conditional compilation, you can chose which exit
>you want. In the current field test, the default is the new,
>more standards comforming version.
Hm. I missed the original post on this, but from the thread I gather you've
broken a lot of code here. We do a lot of:
status = SYS$something
if (!$VMS_STATUS_SUCCESS(status)) exit(status);
and if SYS$something has an iosb:
if (!$VMS_STATUS_SUCCESS(iosb.status)) exit(iosb.status);
Now it looks like I'm going to have to carefully search a lot of code and make
much of it build with the old version of exit() when we get VMS 7.
Bummer.
------------------------------------------------------------------------------
Bob Koehler |
koe...@bessta.gsfc.nasa.gov | rkoe...@author.gsfc.nasa.gov
Exactly my point. I want unix programs to run correctly without
change.
The dilemna is that I also absolutely require DEC C V5.0/OpenVMS V6.2
programs to run without change too. I'm trying to get a sense
of whether I can successfully get people to change their build
procedures to retain old behavior.
> - adopt strategy two, but store the value of the parameter passed
> to exit() as a DCL symbol (say C$STATUS), so that DCL procedures
> which are aware that a C image has just been called can test
> that symbol to determine the "exit code" of the image.
i like charles's idea of exit() creating a separate CLI symbol,
except that the DCL code will look a little screwy:
$ run foobar.exe
$ if f$type($crtl_status) .eqs. "INTEGER"
$ then
$ r0 = $crtl_status
$ else
$ r0 = $status
$ endif
(yeah, i know, it's a worst-case scenario)
unfortunately, this does not solve ken's "problems" --- but then,
i don't particularly agree with him that they are problems.
ok
dpm
---
If I understand the proposal correctly, the new exit() will map the numbers
from 0 to 255 to appropriate VMS error statuses (presumably with meanings
corresponding to the definitions in errno.h) with a facility of the C RTL.
E.g., exit(61) would result eventually in a call to SYS$EXIT with a status
whose facility is the C RTL, whose severity is error (or perhaps severe error),
and whose ident corresponds to text describing the fact that a network
connection attempt was rejected.
I.e., it sounds as if the idea is to make exit(errno) a reasonable thing to do.
The following help file frament fell into my posession from an
alternate universe:
/STANDARD=UNIX
Causes things to be more unix like by default. This causes
the exit(2) function to behave in a unix-like way, rather than
in the more traditional VMS way. This causes ...
(well, it was only a fragment :-).
Warner
--
Warner Losh "VMS Forever" home: i...@village.org
Cyberspace Development, Inc work: i...@marketplace.com
Makers of TIA, The Internet Adapter. http://marketplace.com/
Unix programs that call exit(1) are non-portable as they are relying
on "implementation defined" behavior. If the intent of exit(1) is to
indicate failure (as it usually is), then the Unix code should be
chagned to be exit(EXIT_FAILURE) which is portable.
In the POSIX VMS environment, exit(1) may well have different
semantics (for better Unix compatability - I don't know what the POSIX
standard says about this) than in the DCL environment.
>The dilemna is that I also absolutely require DEC C V5.0/OpenVMS V6.2
>programs to run without change too. I'm trying to get a sense
Here's another idea: toggling the behavior of exit(1) based on
the macro _POSIX_SOURCE or _VMS_SOURCE:
-----
#define _POSIX_SOURCE
#include <stdlib.h>
...
exit(1); /* new 7.0 Unix-like behavior - exit(EXIT_FAILURE) */
-----
#define _VMS_SOURCE
#include <stdlib.h>
...
exit(1); /* old 6.2 behavior - exit(SS_$NORMAL) */
-----
#include <stdlib.h>
...
exit(1); /* old 6.2 behavior - exit(SS_$NORMAL) */
-----
I've read so many remarks on the topic that I have become confused - any
chance of a periodic summary along with your re-explaination?
I rely on my programs being able to return status codes as generated by
$services, usually I $signal the errors but occasionally I exit() them.
I need to retain that behaviour, I need also to be able to view the error
from the CLI (DCL in all cases at my site) without having to "know" that
I need to check a second set of symbols incase the program source was C.
I seldom if ever exit(0) or exit(1) - that just isn't meaningful. If I did
do that I deserve to have it break -- and so do all the unix people. Because
unix is not a standard (there may BE a standard but no two vendors understand
it the same way).
How can the exit status from the image be anything other than the full length
value from the R0 register? Masking out the high order bits is just more work
and results in less INFORMATION (INFORMATION is useful - as opposed to DATA).
I am all in favor of /Standard=(ANSI,HPC,SUNC,VAXC,DECC...) just default to
returning what is passed to exit(). If you want to add macros to define
symbols for EXIT_XXXXX for portability it'd be great, bit don't steal my bits.
>Are you really illiterate? [CHOMP]
poor choice of words, considering that you then say
>Any such change would
>still leave you the option of actually exiting with VMS condition codes, via
>SYS$EXIT or LIB$SIGNAL, for example. In fact, you can, if you wish use either
>the macro:
>
>#define exit LIB$SIGNAL
>
>or
>
>#define exit SYS$EXIT
>
>to cause what would otherwise be a call to the RTL's exit() function to exit
>via one of those mechanisms.
considering that LIB$SIGNAL(foo) will actually cause an image rundown
for only one-eighth of all possible values for "foo". perhaps you meant
LIB$STOP instead?
Assuming that you're talking about programs run in an DCL environment
(as opposed to POSIX, or as "childs" created by some UNIXy method) ...
1.) No. In the interest of compatibility with old versions of VAXCRTL,
where "exit(0)" resulted in a "%NONAME-W-" warning, _many_ VMS C programs
in existence today intentionally use "exit(1)" in order to successfully
terminate a program via exit() at all.
It is not reasonable to have all such programs, or their
compilation procedures changed (for no obvious benefit) ...
In the extreme, this problem _might_ be addressed by both
(a) keeping the "old" behaviour with /STANDARD=VAXC
(b) encouraging people to use /STANDARD=VAXC when compiling
programs (written by someone else) that do "support" VAXC.
BTW, having to add this qualifier in order to compile older C programs
with DECC already has confused _many_ people, and made them think that
they need "all new" C programs with DECC (in particular, on ALPHA) ...
2.) Obviously I and other people have done so on occasion; I concede that
using SYS$EXIT() would have been just as easy - my habit derives from
a VAX FORTRAN background, where CALL EXIT(value) happens to look better
than CALL SYS$EXIT(%val(value)).
Wolfgang J. Moeller, Tel. +49 551 2011516 or -510, moe...@gwdgv1.dnet.gwdg.de
GWDG, D-37077 Goettingen, F.R.Germany PSI%(0262)45050859008::MOELLER
Disclaimer: No claim intended! | moe...@decus.decus.de w.mo...@ieee.org
Never mind.
Mike
Actually, exit(0) is meaningful - or at least well defined. See ANSI 4.10.4.3.
The results of using exit(1) are implementation defined.
>We in the DEC C RTL engineering team need opinions on what to
>do with the C exit() function.
Heheheh... don't tempt me.
Actually, I've never understood why the VMS Engineering staff found it nec-
essary to make exit() massage its parameter in the first place. Let it
act like SYS$EXIT() and let the programmer "#ifdef VMS" when porting Unix
apps. There are enough other places in VAX/DEC C where this has been the
way of doing things, so what's ONE MORE place? Especially if it avoids
so many subtle and intricate issues in the actual implementation of exit()?
That's my two cents' worth of gasoline for the fire, at this time anyway.
Further bulletins as events warrant. ;-)
Chris Chiesa
Chris_F...@cup.portal.com
> Part of the spec for exit (from ANSI C, in fact) is that the
> implementor must define macros EXIT_SUCCESS and EXIT_FAILURE.
> Today, EXIT_SUCCESS is 0 and EXIT_FAILURE is the VMS condition
> value 0x10000002. Most unix implementations define EXIT_FAILURE to
> be 1.
>
> What we've done to date for OpenVMS V7.0 is to implement 2 versions
> of exit(). The old exit accepts a VMS condition code. The new
> exit accepts a number between 0 and 255 -- actually, it silently
> truncates the number into the range of 0 to 255. Through header
> file magic and conditional compilation, you can chose which exit
> you want. In the current field test, the default is the new,
> more standards comforming version. Having the out of the box
> behavior align with standards is the general approach we've take
> for other changes in DEC C V5.2.
>
> What we found that concerns us is old code that calls exit(SS$_NORMAL);
> SS$_NORMAL is the value 1, and we were planning to change EXIT_FAILURE
> to be 1. The concern is that the new (default) exit will treat
> exit(1) as the failure case, not the success case.
>
> We've thought of a range of options, none of which are obviously
> the simple, correct answer. I'm looking for feedback, generally
> around 2 questions:
>
> 1. Is changing the default behavior for programs that recompile acceptable?
NO !
One of the very strong features of VMS is keeping old programs runnin
almost forever !
> 2. Do you rely on exit() taking a VMS condition value?
Someone will do !
(Do you remember the BACKUP/RECORD & READALL case ? Someone will get hit,
they will complain, you will have to change it back, and everyone gets
unsatisfied)
If it did give some substantial programming benefits, then you may consider
it, but I can not imagine any C programmer not capable of using either
the correct macros or some #ifdef'ed stuff. It is not the hard part of
a porting process !
Arne
Arne Vajhøj local DECNET: KO::ARNE
Computer Department PSI: PSI%23831001354030::ARNE
Southern Denmark Business School Internet: AR...@KO.HHS.DK
WWW URL: http://www.hhs.dk/~arne/arne.html
I presume functions registered with atexit() are stored internal to
the C RTL for use by exit() and thus are not available to SYS$EXIT.
Yes and no - but basically no. The C RTL - at least the VAX C RTL, which I
had handy to test - declares an exit handler; the exit handler arranges for
functions passed to atexit() to be called (or atexit() declares its arguments
as exit handlers - I really don't know how the implementation is done).
This is easy to check with a C program less than 10 lines long.
-- Jerry
>ken cowan wrote:
>> We in the DEC C RTL engineering team need opinions on what to
>> do with the C exit() function.
>>[CHOMP]
>> 2. Do you rely on exit() taking a VMS condition value?
>
>Someone will do !
someone already does. it is a documented and supported ability of the
C run-time library under VMS, and has been so for years. what happens
to the value passed to exit() is "implementation-defined" according to
the ANSI C Standard, so i --- and i'm sure many others --- use it as
it has been defined by the vendor (that's you, ken ;-) in the Grey Wall.
Well, if you want it to compile cleanly under DEC C, it might take 10 lines:
main()
{ void finish(), atexit(), puts(), SYS$EXIT();
atexit(finish);
puts("Hello");
SYS$EXIT(1);
}
void finish()
{ void puts();
puts("Goodbye");
Note that he said "programs that recompile." If you've got an executable, it
won't be affected by the proposed changes. Only if you recompile (in which
case you obviously have source code) would the default behavior change.
And what happens when VMS V7 comes out and lots of people start
trying to recompile the hundreds of programs that initially came from
Unix but have already been ported to VMS? This "feature" intended
to make it easier to do new ports will interfere with existing ones.
Some programs that currently handle exit() in a VMS-friendly fashion
will suddenly break, and anybody in the position of trying to maintain
those ports (which happens to include *me* for several prominent,
widely available programs) will start getting questions and bug reports
because existing makefiles and build scripts aren't prepared to cope
with some new conditional option. The fact that the people making
those complaints have access to the source will be small consolation.
Since this proposed feature could only be useful for programs
being written or ported for the first time, it makes no sense to change
the default behavior for everybody just to cater to them.
Pat Rankin, ran...@eql.caltech.edu
They add a single #include statement to the beginning of each of the programs
before they recompile them.
How about this:
#include <stdio.h>
int final (void) { puts("Final running."); return 0; }
int main (int argc, char **argv) { atexit(final); SYS$EXIT(1); }
--John
And I think that our point is that a VMS program exits properly with a
VMS status value in register 0 and that value is, by design, long tradition,
etc. 1 for success, and more complicated values for other statuses. Zero is
not a recognized VMS status value.
exit(1) must work properly. exit(ss$normal) must work properly.
exit(0) must be translated to exit(success) because that is the documented
behavior of the VAX C RTL.
Don't worry so much about running Unix code unchanged. That is
usually not possible even between two different Unix variants. Further,
changing exit(1) to exit(FAILURE) is a trivial sort of change to have to make
and, once made, the statement is ANSI compliant and *should* work properly on
the Unix system as well as the VMS system. Even further, it's the sort of
change that a Unix programmer would make with a sed script or something like
that; a million lines of code ported in a few seconds! And the worst that's
likely to happen when improperly ported Unix code is run under VMS is that it
will exit with NONAME...NOMESSAGE.
IOW, it ain't broke; don't fix it!
>The dilemna is that I also absolutely require DEC C V5.0/OpenVMS V6.2
>programs to run without change too. I'm trying to get a sense
>of whether I can successfully get people to change their build
>procedures to retain old behavior.
>
--
*************************************************************************
* Here, there be dragons! *
* DRA...@CIS.CompuServe.Com *
* *
* Richard B. Gilbert *
*************************************************************************
Well, if you want it to compile cleanly under DEC C, it might take 10
lines:
main()
{ void finish(), atexit(), puts(), SYS$EXIT();
atexit(finish);
puts("Hello");
SYS$EXIT(1);
}
void finish()
{ void puts();
puts("Goodbye");
}
You didn't try very hard:
final()
{ printf("Final running\n");
}
main()
{ printf("Going...");
atexit(&final);
SYS$EXIT(1);
}
I don't have DEC C installed at the moment, but this program should *compile*
cleanly: ANSI doesn't *require* you to declare functions; the old K&R C rule
that undeclared functions are taken to return an int still holds. (It's true
that the standard does *not* require that the program *work* as written,
since printf() is a variadic function, and that need not work unless declared.
OK, follow your idea and use puts() instead - or, better, #include <stdio.h>;
I've only got 8 lines so far, three wasted (the one to print "Going..." and
the ones with just "}" on them) so I can include that and still be under my
limit. Hell, add a #include <stdlib.h> to get atexit's declaration just to be
sure!
-- Jerry
=I don't have DEC C installed at the moment, but this program should *compile*
=cleanly: ANSI doesn't *require* you to declare functions; the old K&R C rule
=that undeclared functions are taken to return an int still holds.
By "compile cleanly" I meant compile without having the compiler generate any
warnings, errors, or informational messages. In the case of your program, we
get:
{ printf("Final running\n");
........^
%CC-I-IMPLICITFUNC, In this statement, the identifier "printf" is implicitly
declared as a function.
At line number 2 in ST$USER:[CARL]TEST.C;113.
{ printf("Going...");
........^
%CC-I-IMPLICITFUNC, In this statement, the identifier "printf" is implicitly
declared as a function.
At line number 5 in ST$USER:[CARL]TEST.C;113.
atexit(&final);
........^
%CC-I-IMPLICITFUNC, In this statement, the identifier "atexit" is implicitly
declared as a function.
At line number 6 in ST$USER:[CARL]TEST.C;113.
SYS$EXIT(1);
........^
%CC-I-IMPLICITFUNC, In this statement, the identifier "SYS$EXIT" is implicitly
declared as a function.
At line number 7 in ST$USER:[CARL]TEST.C;113.
%VCG-I-SUMMARY, Completed with 0 error(s), 0 warning(s), and
4 informational messages.
At line number 8 in ST$USER:[CARL]TEST.C;113.
It's Monday morning and there must have been a dozen posts on this
topic that I just read. I can't reply to every single one, so I'll
try to summarize.
First, a bit of philosophy. The direction of the DEC C RTL
is to be the best possible user-mode emulation of unix.
Currently, unix is defined by XPG4 V2 (from the X/Open consortium),
and is based on some formal standards, including ISO POSIX-1 and ANSI C.
What I've heard here is
1. that an overwhelming majority of you like the current behavior and
that we should not change the default.
2. that we need to clearly document what we're doing
In response to those who say exit() isn't broken, I must respectfully
disagree. One of our major software partners added this to their
wishlist of things we'd fix. I also experienced the need to
return more data than just success or failure from a child process
when I was testing pipes and mmap().
I vote vehemently in favor of the broad interpretation of "code",
specifically to include makefiles, build.com files, etc., not just
the C language source code of the software.
==================================================================
Dick Piccard Academic Technology Manager
Computer Services
pic...@ouvaxa.cats.ohiou.edu Ohio University
Not really. Saying that C is the preferred language for writing device drivers
is NOT the same thing as saying that the C RTL should be used in device
drivers.
"pipes and mmap()" do not represent portable C programs; there's
far more to the C world than ANSI and X/Open. You can just as easily
request increased-pseudo-Unix behavior at compile time specifically for
programs that want it. Changing the default behavior is effectively
forcing every existing C program to need investigation about whether
they must be conditionally compiled.
I thought that C was supposed to have become the preferred language
for writing device drivers for Alpha/VMS. That's a fundamental conflict
with "Unix emulation". Device drivers don't use exit(), but that's
irrelevant to whether native VMS ends up being _perceived_ as a second
class platform for its own C implementation.
Pat Rankin, ran...@eql.caltech.edu
The problem arises only with non ANSI-compliant code that uses exit(0)
for success and exit(1) for failure. Perhaps your software partner should
simply s/exit(1)/exit(FAILURE)/whole and s/exit(0)/exit(SUCCESS)/whole.
Exit, as used in Unix *is* broken! Unix is broken! The Unix culture
has an attitude like "Feel privileged that you have been told that there has
been some sort of an error. And don't ask exactly what the error was or what
to do about it, it's not the operating system's business to tell you!"
At least VMS tells you, to the best of its ability, what the problem
is. It's not perfect by any means but it's far better than Unix. There is no
thrill/chill quite like having your disk backup die with "Error 35" and no
explanation of "Error 35" in sight!
Please keep in mind that your compiler and RTL support the VMS
Operating System and VMS users!!! If I wanted to run Unix, I would have
bought Unix! I have used Unix and have been a Unix Systems Administrator for
three years. Given a choice, I wouldn't have it on a bet!
>In response to those who say exit() isn't broken, I must respectfully
>disagree.
it might be "broken", but not by the ANSI C Standard definition of exit().
could you please re-phrase your description? the part about wait()
keeping only the low eight bits i can agree is a wart, but passing a
value to exit() is implementation-defined. since you are the vendor,
there's no need to claim that you need to "meet the standard" ---
you have the right to change it anytime you feel it necessary.
of course, we'll all switch to GNU C if you do.
>One of our major software partners added this to their
>wishlist of things we'd fix.
it sounds like this "partner" has existing code with a jillion exit(foo) calls
which he doesn't want to change with a jillion #ifdef VMS #else #endif edits.
of course, i'm just guessing ;-)
it also sounds like you want the minimal C program to exit(foo)
without signalling, without any command line qualifiers, without any
special headers, without any special macros or pragmas, period.
since you have no control over the CLI this means that exit() must
mangle the value so that "foo" is not the value actually returned
as $STATUS, so i *still* don't see the point of this exercise, so sorry.
The new exit behavior is interesting, but should only be enabled when
you say /STANDARD=UNIX or /DEFINE=__UNIX_STANDARD, rather than the
default. It wouldn't be hard to add to makefiles for porting (that
you'll likely have to write from scratch anyway), and it wouldn't
break anything currently existing.
Just my two cents.
Writing device drivers in C doesn't conflict with "unix emulation" at
all. Unlike VMS POSIX which needs an captive environment, we're
doing user-mode "best effort" emulation. It's not exact, but it
does mean you get a regular native VMS .exe when you're done.
lrdriver.c can still call exe_std$queue_fork or whatever other
driver gizmos it needs.
If products stop showing up on VMS, then it'll be perceived a
As I was saying ...
Writing device drivers in C doesn't conflict with "unix emulation" at
all. Unlike VMS POSIX which needs an captive environment, we're
doing user-mode "best effort" emulation. It's not exact, but it
does mean you get a regular native VMS .exe when you're done.
lrdriver.c can still call exe_std$queue_fork or whatever other
driver gizmos it needs.
If products stop showing up on VMS, then it'll be perceived as a
2nd class OS. If we make it easier (read cheaper) for ISVs to port,
then it's more likely we'll get the products ported.
Someone else said "if it ain't broke, don't fix it". It's not broken
by the ANSI C definition. It's ISO POSIX-1 definition where we're lacking.
ISO POSIX-1 is upward compatible with ANSI C, but it places additional
burdens on the implementor. It's actually in the description of
wait and waitpid in ISO POSIX-1 that the requirements are most
clearly spelled out.
For those of you who want an ANSI C product and don't need any 'unix'
functionality, you already have it. Some ISVs need more from us, and that's
what we're targetting.
As I said in reply to Pat Ranklin, I think it benefits the whole user
community too if it means things like Netscape browsers show up
more readily.
I can't recall any responses that claimed you shouldn't change
exit() at all. But I have yet to see any justification for changing
its _default_ behavior, which is what your initial posting discussed.
"Make it more Unix like" is an explanation, but not justification.
You asked for comments, you're getting them: changing exit()'s
default behavior is a bad idea. The choice is whether new Unix ports
need to ask for more Unix-like behavior [sic], versus whether existing
ones need to avoid it when they're eventually recompiled. Changing the
default suggests that requiring something like /define=_XOPEN_SOURCE
is more of a burden for new code than requiring /undefine=_XOPEN_SOURCE
is for existing code, and that is clearly not the case. Most vendors
are already aware of the need for -D_XOPEN_SOURCE on some platforms
[including VMS POSIX!], so hiding that need on VMS isn't much of a
benefit. Forcing explicit changes to existing native VMS code _and_
existing ports of Unix code is a tangible detriment.
Pat Rankin, ran...@eql.caltech.edu
I don't have the official POSIX or X/Open documents available as I do
the ANSI C spec, so I can't site chapter and verse...but I believe
POSIX requires that the macro _POSIX_SOURCE be defined by the
programmer (not the implementation) to indicate a POSIX compliation.
I wouldn't be surprised if that was the case for X/Open as well.
Some Unix vendors (HP for example) have things set up so that you can
easily get a larger set of standard APIs - the default environment is
ANSI C. So on my HP
% c89 exit.c # only ANSI C function protos and macros
% c89 -D_POSIX_SOURCE # POSIX, open() for example
% c89 -D_XOPEN_SOURCE # X/Open, message catalogs for example
% c89 -D_HPUX_SOURCE # everything, socket API
Other vendors have similar schemes - under Digital UNIX (OSF/1), you
need to add -D_OSF_SOURCE.
DEC C w/o and command line qualifiers results in strict ANSI C, to use
open() for example it is necessary to add /PREFIX_LIBRARY_ENTRIES=ALL_ENTRIES.
I think this practice combined with macros like the above should be
used to control which exit() routine is used at compile time. So if
its X/Open semantics of exit() that you want, then
$ cc/prefix=xopen exit.c ! exit() calls decc$xopen_exit()
(or $ cc/define=(_XOPEN_SOURCE) exit.c )
$ cc exit.c ! exit() calls existing decc$exit()
What if we extend this a little bit?
How about adding the following routines to the C runtime:
exit_vms()
Takes a VMS condition status code and returns it as the image's
termination status, i.e., the existing exit().
exit_unix()
exit() as "defined" by UNIX. exit(1) returns an error status (as does any
other non-zero value) so that non-standard UNIX code will work correctly.
exit_errno()
Maps errno into a meaningful VMS condition status code which is returned
as the image's termination status.
By default, exit() is exit_vms(). exit() can be mapped to exit_unix() with
an appropriate #define and/or compiler switch.
This allows existing code to work with no changes. New or ported code has
the option of following UNIX "conventions". Hybrid code can use one exit
method in one place and another elsewhere by explicitly calling the
appropriate exit handler, if necessary, or by using appropriate
compilation switches on a per source basis.
------------------------------------------------------------------------
Chris Scheers, Applied Synergy, Inc.
817-237-3360 (Voice) 817-237-3074 (Fax) Internet: a...@airmail.net