catching exit

J

jameskuyper

CBFalconer said:
Which is easy. Simply set an error flag visible in the caller, and
return. That value may be the value returned by the function.

No, it's not that simple. Replacing

exit(status);

with

some_global = status;
return;

will not handle any of the numerous complications that have already
been mentioned elsewhere on this thread: memory leaks, files that were
not closed, at_exit() handlers (admittedly not a common problem). In
general, the kind of person who uses exit() doesn't merely ignore
memory leaks and unclosed files; such a person generally is actively
relying on exit() to handle those details. Such things can usually be
found in any program that calls exit().

Furthermore, the calling function may have been designed based upon
the assumption that the called function would only return if the
termination condition didn't come up. Since the termination condition
did come up, replacing "exit();" with "return;" may require an
extensive re-write of the calling function. Been there, done that
(quite recently) - it was not simple, it was not easy, it kept me very
busy for several days, and I finished it that quickly only because I
realized that I did not have the time I needed to perform the complete
re-design that I should properly have performed.
 
K

Kenny McCormack

Richard Heathfield <[email protected]> wrote:
[a strategy to prevent stupid posts from CBF]
This is a keeper. Well done, Mr. H!

Yes... but I'm not sure about this bit:

Of course, by this stage every single reply should have been deleted,
but just in case one slips through I'd recommend changing this to

(3) Now send any undeleted replies to /dev/null.

Aye - as someone else posted in one of these threads today - there is
always room for improvement.
 
M

mathieu

The real problem, I presume, is that you have exit calls from
functions other than main().  In the original version of the program,
each such call terminates the main program; in your bigger program
with main renamed to mymain, you want to terminate mymain, not your
new main.  Right?
Correct.

Keeping it as a separate program and invoking it with system() might
be your best bet.  The behavior of system() is largely
implementation-defined, particularly its return value, but if you're
only targeting a limited number of systems you can deal with that with
a few #ifdef's.

If you want the resulting code to be portable to all conforming
systems, things are a bit more difficult.  On any one system, you
should be able to tell from the result returned by system() whether
the invoked program did an exit(EXIT_SUCCESS) or an exit(EXIT_FAILURE)
(or some other system-specific value), but there's no portable way to
do that.
:(

You'll also need to take some care to ensure that
system("existing_program") actually invokes what you want it to
invoke.  The details are system-specific, but at least for Unix-like
and Windows-like systems, think about PATH settings.
ok

<OT>
Here's another possibility.  I happen to know that there's another
language, whose name is that of our local favorite language with a
couple of plus signs appended to it, which supports the kind of
control flow you're looking for.  Rather than calling exit, you can
"throw" an "exception" and "catch" it at whatever level you like
rather than letting it propagate out and terminate the program.  It's
not inconceivable that you could recompile this program using a
compiler for this Other Language and make use of the OL's features.
This approach could be fraught (fraught, I say!) with peril.  There
are subtle differences between C and the OL, some of which may prevent
valid C code from compiling, and some of which may silently change its
behavior.  And if you take that approach, we can't help you here, but
the folks over in comp.lang.thatotherlanguage or
comp.lang.thatotherlanguage.moderated will be glad to do so.
</OT>

pure genius ! I actually happen to be using this you-shall-not-name
language you are talking about. This definitely solve the issue with
the 'exit' calls. But as Eric (see early posts) mention, this is only
the visible part of the iceberg. The code is also covered with globals
that are randomly initialized in different places.

But still, I think that system() is your best bet, requiring no
changes to the program and (probably) just a little bit of
system-specific scaffolding.

alright, I am convinced.

Thanks all for your time,
-Mathieu
 
W

Willem

mathieu wrote:
) I am trying to reuse a piece of code that was designed as an
) application. The code is covered with 'exit' calls. I would like to
) reuse it as a library. For that I renamed the 'main' function into
) 'mymain', but I am stuck as to what I should do for the 'exit'.
)
) AFAIK there is no portable way to catch the exit. The only thing I
) can think of is atexit, but that does not work since 'exit' is still
) called afterward.
)
) What I am thinking now is that I need to replace all exit(val) with
) longjmp(env, val). And make 'env' global.
)
) Comments ?

Do you have some form of fork() in your implementation ?

If so, you could fork the process and call mymain() from there, and in the
main process, wait for the exit status. This is the midway solution
between having the code in the same executable, and using system().

Depends on how portable you want the code to be, of course.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
K

Keith Thompson

mathieu said:
pure genius ! I actually happen to be using this you-shall-not-name
language you are talking about. This definitely solve the issue with
the 'exit' calls. But as Eric (see early posts) mention, this is only
the visible part of the iceberg. The code is also covered with globals
that are randomly initialized in different places.

Yes, there are some important points that I missed in suggesting the
"Other Language" solution. C program startup and shutdown provide
some additional functionality that you don't get in a function call.

On startup, objects with static storage duration are initialized
(explicitly or implicitly), and the standard I/O streams are opened.
On shutdown, allocated memory is *typically* deallocated (the standard
doesn't guarantee this, but it's common enough that it's likely this
program relies on it), the standard I/O streams are closed, and
probably some other stuff happens. If you turn the program into a
callable function, you'll have to perform some of these implicit
actions explicitly.
alright, I am convinced.

Good luck.

Out of curiosity, how portable does your final program need to be? If
all you need to worry about are, say, Unix-like and Windows-like
systems, dealing with the vagaries of system() shouldn't be very
difficult. If you can restrict yourself to POSIX, you're in even
better shape. If you want your code to compile and run on the DS9K,
it's going to be trickier.
 
M

mathieu

Out of curiosity, how portable does your final program need to be?  If
all you need to worry about are, say, Unix-like and Windows-like
systems, dealing with the vagaries of system() shouldn't be very
difficult.  If you can restrict yourself to POSIX, you're in even
better shape.  If you want your code to compile and run on the DS9K,
it's going to be trickier.

It's all there: http://gdcm.sourceforge.net

So far I have only been dealing with GCC/Linux, VC/Win32 (no Win64 so
far), GCC/MacOSX. So it's not that difficult indeed... Well
theoretically.

<OT>
One of the main feature people like about this toolkit, is that it is
wrapped in Python (using swig). One of my user started using 'py2exe'
which basically gathered all the python modules + a lightweight python
interpreter in a fake executable (AFAIK). So I am now concerned that
within this py2exe executable, it would be like being in a chroot
environment and I might not even have access to a shell to execute a
system call.
But that's a different story, in a far far away newsgroup.
</OT>

<OT #2>
I am also concerned on how I am supposed to find the executable from
my python module since the exe might not be in the path. I have played
a little with GetModuleFileName (win32) and /proc/self/exe (proc
system), but this is again something with lots of #ifdef not easily
portable.
</OT #2>

-Mathieu
 
C

CBFalconer

CBFalconer wrote:
.... snip ...


No, it's not that simple. Replacing

exit(status);
with
some_global = status;
return;

will not handle any of the numerous complications that have already
been mentioned elsewhere on this thread: memory leaks, files that were
not closed, at_exit() handlers (admittedly not a common problem). In
general, the kind of person who uses exit() doesn't merely ignore
memory leaks and unclosed files; such a person generally is actively
relying on exit() to handle those details. Such things can usually be
found in any program that calls exit().

Yes it will, provided that the calling function does those things.
I.e. the calling code is something like:

err = newfunct(...);
if (err & BADBITS) {
cleanupwhatever();
decidewheretogonext();
}
else {
alliswellwithnewfunct();
...
}

It may be a pain in the butt to write 'cleanupwhatever' and
'decidewheretogonext'. There is no problem replacing the calls to
exit with returning something, since the OP obviously has the
source code.
 
K

Keith Thompson

CBFalconer said:
It may be a pain in the butt to write 'cleanupwhatever' and
'decidewheretogonext'. There is no problem replacing the calls to
exit with returning something, since the OP obviously has the
source code.

Are you (still!) assuming that the existing calls to exit are only
within the main function?

exit() could be called from anywhere within any function within a very
large existing program. Calling exit() terminates the program. If
the program is changed into a piece of a new larger program, keeping
the same semantics means terminating the function containing the call
to exit, and the function that called it, and the function that called
*that* function, up to *but not beyond* the function that was formerly
called "main".

Replacing the calls to exit with returning something is decidedly
non-trivial.
 
J

James Kuyper

CBFalconer said:
Yes it will, provided that the calling function does those things.
I.e. the calling code is something like:

err = newfunct(...);
if (err & BADBITS) {
cleanupwhatever();
decidewheretogonext();
}
else {
alliswellwithnewfunct();
...
}

It may be a pain in the butt to write 'cleanupwhatever' and
'decidewheretogonext'. There is no problem replacing the calls to
exit with returning something, since the OP obviously has the
source code.

He didn't tell us how many different functions there were that called
exit(). He also didn't tell us how many different places in the program
that those functions are called from. However, if he's seriously
considering a myexit() function which calls longjmp(), I suspect that
there are probably at least a dozen such calls. If I understand what
you're suggesting properly (which is far from clear), he'll have to
figure out, at almost every place on the call chain connecting main() to
exit(), what the equivalent of cleanupwhatever(), decidewheretogonext()
and alliswellwithnewfunct() should be; in general, it will be different
at each of those locations.

It's certainly possible (I just recently got through doing something
similar), but I don't see how it can be described as "easy".
 
J

James Kuyper

CBFalconer said:
That wasn't clear to me. Since the only things you can (portably)
return from main is EXIT_SUCCESS and EXIT_FAILURE (and 0), you have
much more latitude in a function. So simply return from the
function, returning a status, and let the caller decide what to do
about it. I see no point to the exit calls. Maybe you do.

I don't quite follow the point of your criticism. The exit() calls were
not put into the code by mathieu. He's trying to figure out what to
replace them with. What did he say to make you think he didn't
understand how exit() works? Are you assuming that the exit() calls are
coming from within main() itself? That's the only way I can make your
objections seem to make sense, but I can't figure out why you'd assume that.
 
C

CBFalconer

James said:
I don't quite follow the point of your criticism. The exit()
calls were not put into the code by mathieu. He's trying to
figure out what to replace them with. What did he say to make
you think he didn't understand how exit() works? Are you
assuming that the exit() calls are coming from within main()
itself? That's the only way I can make your objections seem to
make sense, but I can't figure out why you'd assume that.

I didn't criticize, at least I don't think so. I made suggestions
about how to perform his port. If some of my assumptions about the
(never shown) code he wants to replace are false, then some of the
suggestions are pure blooey.
 
M

mathieu

I didn't criticize, at least I don't think so.  I made suggestions
about how to perform his port.  If some of my assumptions about the
(never shown) code he wants to replace are false, then some of the
suggestions are pure blooey.

As I said before it's is called 'PVRG JPEG 1.2.1' you can google for
it. Or see my integration in GDCM:

http://gdcm.svn.sourceforge.net/viewvc/gdcm/trunk/Utilities/pvrg/

And yes there are *plenty* of exit all over the place (read: in
functions other than the original 'main').

$ grep exit\( * | wc
75 152 2479

Which are spread in different files:

$ grep -l exit\( * | wc
8 8 68

And no this code is not easy to follow (slightly easier to follow than
IJG, since less complex)

-M
 
C

CBFalconer

mathieu said:
As I said before it's is called 'PVRG JPEG 1.2.1' you can google
for it. Or see my integration in GDCM:

http://gdcm.svn.sourceforge.net/viewvc/gdcm/trunk/Utilities/pvrg/

And yes there are *plenty* of exit all over the place (read: in
functions other than the original 'main').

$ grep exit\( * | wc
75 152 2479

Which are spread in different files:

$ grep -l exit\( * | wc
8 8 68

And no this code is not easy to follow (slightly easier to follow
than IJG, since less complex)

My reaction is UGH. I suspect writing your function from scratch
will be easier.
 
J

James Kuyper

CBFalconer said:
....
I didn't criticize, at least I don't think so.

I think that the your comment cited above sounds fairly critical.

... I made suggestions
about how to perform his port. If some of my assumptions about the
(never shown) code he wants to replace are false, then some of the
suggestions are pure blooey.

He gave us a link to the code at <http://gdcm.sourceforge.net> on Thu,
14 Aug 2008 13:53:51 -0700 (PDT).

I don't know for sure what assumptions you made, but it has seemed to me
during this discussion that your comments made sense only if you were
assuming that all of the exit() calls were from within main(). I don't
think that assumption was ever plausible, given that his very first
message asked about the feasibility of solving his problem by replacing
exit() with longjmp(). That he asked that question doesn't prove that
exit() was being called from a subroutine - but it does make it pretty
likely. If he was just thinking about about using longjmp() to move
around main() itself, then replacing setjmp() with a statement label,
and longjmp() with a 'goto' would be a lot simpler.
 
C

CBFalconer

James said:
I think that the your comment cited above sounds fairly critical.

Good lord. You consider "That wasn't clear to me." to be
critical? I am amazed.
 
J

James Kuyper

CBFalconer said:
Good lord. You consider "That wasn't clear to me." to be
critical? I am amazed.

That depends upon the thing you're not clear about. In this case, you
were not clear about whether he had basic reading skills and a
sufficiently strong understanding of C to use those reading skills to
understand the man page for exit(). In this group, suggesting that
someone might be lacking such elementary skills constitutes criticism,
at least, even if it doesn't quite qualify as an outright insult.
Someone who's even thinking about using longjmp() had better have a much
higher skill level than that.
 
A

Antoninus Twink

CBFalconer wrote: [same old same old]
In this case, you were not clear about whether he had basic reading
skills and a sufficiently strong understanding of C to use those
reading skills to understand the man page for exit().

Maybe CBF just assumes everyone else has the same problems he obviously
does with basic reading comprehension.
 
R

Richard

Antoninus Twink said:
Richard Heathfield <[email protected]> wrote:
[a strategy to prevent stupid posts from CBF]
This is a keeper. Well done, Mr. H!

Yes... but I'm not sure about this bit:

Of course, by this stage every single reply should have been deleted,
but just in case one slips through I'd recommend changing this to

(3) Now send any undeleted replies to /dev/null.

I would have thought it could be shortened to

"Please do not post to my private playground as you are a silly,
clueless fool who constantly makes a tit of himself"
 
D

David Thompson

Keeping it as a separate program and invoking it with system() might
be your best bet. <snip>

On the evidence seen so far, concur.
<OT>
Here's another possibility. I happen to know that there's another
language, whose name is that of our local favorite language with a
couple of plus signs appended to it, which supports the kind of
control flow you're looking for. Rather than calling exit, you can
"throw" an "exception" and "catch" it at whatever level you like
rather than letting it propagate out and terminate the program. It's
not inconceivable that you could recompile this program using a
compiler for this Other Language and make use of the OL's features.
This approach could be fraught (fraught, I say!) with peril. There
are subtle differences between C and the OL, some of which may prevent
valid C code from compiling, and some of which may silently change its
behavior. And if you take that approach, we can't help you here, but
the folks over in comp.lang.thatotherlanguage or
comp.lang.thatotherlanguage.moderated will be glad to do so.
</OT>
That will give you the nonlocal jump -- like setjmp/longjmp already
discussed, in a slightly nicer form -- but it won't help clean up
resources allocated the C way (malloc, fopen, etc.), which the
existing code presumably uses given it is C. You would have to convert
to OL-style 'RAII' manager classes. And rewriting the now-library to
that extent is almost certainly more work than just rewriting it in
library-friendly C.

- formerly david.thompson1 || achar(64) || worldnet.att.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,152
Latest member
LorettaGur
Top