mathieu
8/14/2008 7:00:00 AM
On Aug 13, 8:17 pm, Eric Sosman <Eric.Sos...@sun.com> wrote:
> mathieu wrote:
> > Hi there,
>
> > 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 ?
>
> If you can change the source of the application, you can replace
> exit() calls with myexit() calls and then do what you like, including
> calling longjmp() to transfer back to a "wrapper." But that's not
> likely to solve everything, unless the application has already cleaned
> itself up before calling myexit(). If it hasn't, there may still be
> open files and un-free()d memory hanging around ...
>
> If the application uses atexit(), you're going to have to decide
> what to do about the functions it's registered and that it thinks are
> going to run when it calls exit(). Should they run even though the
> application isn't really exiting? Should they run only when the whole
> wrapped program exits? Either way, you've got some work to do: You'll
> probably need a myatexit() that registers functions that myexit() can
> run (and de-register), or a myatexit() that recognizes double-registered
> functions when the wrapped application re-runs and suppresses the extra
> calls to atexit(). (This carries some risk of changing the semantics,
> by the way: exit() runs the functions in reverse order of registration,
> so if the application registers f() and then g() the first time, but
> g() and then f() the second, it's not clear what should happen.)
>
> Yet another thing to beware of is "run-once" code that initializes
> something the first time a function is called. These things often
> test a local static variable inside the function to see whether this
> is the first call, and your problem is to figure out which of these
> should really be "run-once" and which should be "run-once per cycle,"
> and to make arrangements to reset the triggers of the latter.
>
> ... and there's probably some other gotchas I haven't thought of.
> This has the potential to become a very messy job indeed.
>
> One alternative is to rewrite the code, keeping in mind that it
> will be invoked multiple times in the new framework and writing
> accordingly. This might be a lot of work, but it will be less work
> than writing the code from scratch took (because you can study the
> old code while you write the new), and it might turn out to be less
> work than trying to hack the exit() calls.
>
> Another possibility is to leave the code as it stands, and run
> it as a separate program. You could use the system() function to
> launch the application and wait for it to finish, possibly preparing
> input files for it first and reading its output files afterward.
>
> Changing a program's "framework" is seldom easy. Good luck!
Hi Eric,
Thanks for your input, esp. the issue with globals. This is
something I have not thought about.
As a first step, I'll replace exit with myexit+longjmp. Then as a
second step, I'll rewrite the portion that is doing the initialization
of the globals (within a func). Calling this init func will simply
reproduce the old behavior. Hopefully the library is simple enough so
that I can get rid of all leaks quickly (thanks to valgrind).
Thanks, that was very helpful !
-Mathieu