Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I undo or remove an atexit command?

If I place atexit( fn ); on the exit stack, it will get executed when the program exits: returns from main() or via exit().

Can I remove it from the stack?

Why do I want to do this, you ask?

I was experimenting with a simple try-catch mechanism using atexit, setjmp and longjmp. It would be just perfect if I could undo-atexit(fn); - even if it would only work for the last registered function.

Edit:

Following monoceres' suggestion to make my own stack...

The stack only works with one exception catcher for now.

void (*_catchFn[10])()  = {0,0,0,0,0,0,0,0,0,0};

void _catch(){
  if ( _catchFn[0] != 0 ){
    (_catchFn[0])();
  }
}

void _addCatch( void (*fn)() ){
  _catchFn[0]=fn;
}

void _remCatch( void (*fn)() ){
  _catchFn[0]=0;
}

void test(){
  jmp_buf env;

  void catch(){                  // we get here after an exit with a registered catch
    longjmp(env,1);              // return to the line marked except...
                               //   that first will get the value 1
  }
  int first = setjmp( env);      // ** return here **
  fprintf( stderr , "test: After setjmp. first=%d\n" , first );
  if( first == 0 ){              // try this code
    _addCatch(catch);            // register the catch function to 'catch' the exit
    fprintf( stderr , "test: Before CHECK\n" );
    // CHECK something and something bad happens and it exits
    exit(1);                     // like this
    fprintf( stderr , "test: After CHECK - THIS SHOULD NEVER BE SEEN AFTER AN EXCEPTION.\n" );
  }else{
    fprintf( stderr , "test: After longjmp return. first=%d\n" , first );
  }
  _remCatch( catch);
  fprintf( stderr , "test: IT WORKED!\n");
  exit(1);  // exit again to see if we are safe
}

int main(){
  atexit( _catch );              // register my global exception stack
  test();
}
like image 423
philcolbourn Avatar asked Feb 22 '10 11:02

philcolbourn


People also ask

What is the use of atexit () function?

The function pointed by atexit() is automatically called without arguments when the program terminates normally. In case more than one function has been specified by different calls to the atexit() function, all are executed in the order of a stack (i.e. the last function specified is the first to be executed at exit).

How does Atexit work in C?

In the C Programming Language, the atexit function registers a function as a termination function which is called if the program terminates normally. When calling the atexit function more than once, the last function to be registered is the first function that will be called when the program is terminated normally.


2 Answers

Why not build your own stack that you call from a single atexit() function? That way you could manipulate the stack all you want.

like image 177
monoceres Avatar answered Oct 24 '22 10:10

monoceres


No, you cannot do it, but you can use global flag so your exit handler will be doing nothing if the flag is set.

Alternatively you can call _Exit() (C99) - it will perform normal exit procedure (close all open descriptors, send all needed signals and parent/children) but will not call exit handler.

like image 33
qrdl Avatar answered Oct 24 '22 09:10

qrdl