Test des applications dans des conditions de mémoire faible

La question de savoir s'il est nécessaire de vérifier quels retours mallocest controversée et suscite toujours un débat animé.



Certaines personnes pensent que nous devrions essayer de gérer toutes sortes d'erreurs d'exécution, y compris. et les situations du MOO. D'autres pensent qu'il y a encore peu de choses à faire avec MOO, et il vaut mieux laisser l'application planter. Du côté du deuxième groupe de personnes, il y a aussi le fait que la logique de traitement supplémentaire du MOO est difficile à tester. Et si le code n'est pas testé, cela ne fonctionne presque certainement pas.



Je suis tout à fait d'accord que vous ne devriez pas implémenter une logique de gestion des erreurs que vous n'allez pas tester. Cela n'améliorera presque certainement rien, et peut-être même pire - tout gâcher.



La question de savoir s'il faut ou non essayer de gérer les situations MOO dans les bibliothèques / applications est controversée et nous n'y reviendrons pas ici. Dans le cadre de cette publication, je souhaite simplement partager mon expérience sur la façon dont vous pouvez tester la logique implémentée pour gérer les situations MOO dans les applications écrites en C / C ++. La conversation portera sur les systèmes d'exploitation Linux et macOS. Pour un certain nombre de raisons, Windows sera contourné.



introduction



Nous souhaitons tous que MOO ne se produise jamais, mais dans la vraie vie, cela n'est pas toujours possible pour les raisons suivantes:



  • La RAM est toujours limitée.
  • SWAP n'est pas toujours activé.
  • Les applications ne se comportent pas toujours correctement et tentent parfois d'allouer des quantités de mémoire irréalistes, interférant avec elles-mêmes et avec les autres.
  • Les applications 32 bits existent toujours.
  • overcommit n'est pas toujours activé.
  • La consommation de mémoire peut être limitée en utilisant ulimit, par exemple.
  • LD_PRELOAD .


, , , OOM . , , :



  • , - .
  • OOM . .
  • . , .


, , SQLite. , . . SQLite .



, , , . OOM Killer, , . , C++, .



1.



, OOM . my_malloc my_free malloc free.



my_free . my_realloc.



my_malloc malloc . my_malloc , NULL .



, :



  • 3rd party .
  • malloc . - strdup.
  • malloc’ , , .
  • C++ malloc free.


- .



2.



Linux LD_PRELOAD. . malloc. , malloc/realloc/free (weak). , macOS LD_PRELOAD, DYLD_INSERT_LIBRARIES.



, , LD_PRELOAD DYLD_INSERT_LIBRARIES malloc/realloc NULL .



, "" . , .



, "" , , . :



  • main. , .
  • Runtime macOS " ". , , , .
  • printf macOS SIGSEGV/SIGBUS.
  • , std::bad_alloc, . , , , OOM. std::terminate. .
  • std::thread std::terminate macOS.


UPDATE: Travis CI , macOS / Xcode , std::bad_alloc , std::thread std::terminate.



Overthrower. - malloc NULL. Overthrower - , .



3.



main



, main , main runtime . main, , .. - main.



, main . Overthrower, OOM . Overthrower , .



:



  • activateOverthrower
  • deactivateOverthrower


:



#ifdef __cplusplus
extern "C" {
#endif
void activateOverthrower() __attribute__((weak));
unsigned int deactivateOverthrower() __attribute__((weak));
#ifdef __cplusplus
}
#endif


.



Overthrower LD_PRELOAD, NULL, , .



, , :



int main(int argc, char** argv)
{
    activateOverthrower();
    // Some code we want to test ...
    deactivateOverthrower();
}


activateOverthrower/deactivateOverthrower , :



TEST(Foo, Bar)
{
    activateOverthrower();
    // Some code we want to test ...
    deactivateOverthrower();
}


, -, , Overthrower , :



#ifdef __cplusplus
extern "C" {
#endif
void pauseOverthrower(unsigned int duration) __attribute__((weak));
void resumeOverthrower() __attribute__((weak));
#ifdef __cplusplus
}
#endif


:



TEST(Foo, Bar)
{
    activateOverthrower();
    // Some code we want to test ...
    pauseOverthrower(0);
    // Some fragile code we can not fix ...
    resumeOverthrower();
    // Some code we want to test ...
    deactivateOverthrower();
}


Overthrower .





__cxa_allocate_exception, , , malloc, NULL. , Linux, malloc, __cxa_allocate_exception (emergency buffer), , . .



macOS , , , , std::bad_alloc, std::terminate.



UPDATE: , macOS / Xcode .



, , , __cxa_allocate_exception malloc. - Overthrower’ malloc. Overthrower malloc __cxa_allocate_exception.



, , , macOS __cxa_atexit, Linux dlerror. .



Overthrower , malloc free. Overthrower’ , activateOverthrower deactivateOverthrower , :



overthrower got deactivation signal.
overthrower will not fail allocations anymore.
overthrower has detected not freed memory blocks with following addresses:
0x0000000000dd1e70  -       2  -         128
0x0000000000dd1de0  -       1  -         128
0x0000000000dd1030  -       0  -         128
^^^^^^^^^^^^^^^^^^  |  ^^^^^^  |  ^^^^^^^^^^
      pointer       |  malloc  |  block size
                    |invocation|
                    |  number  |


Overthrower , , .



Overthrower’, , valgrind. , OOM. , , Overthrower . Overthrower , , deactivateOverthrower , stderr .





Overthrower 3 :



  • Random — rand() % duty_cycle == 0. duty_cycle, .
  • Step — (malloc_seq_num >= delay), delay .


<--- delay --->
--------------+
              |
              | All further allocations fail
              |
              +------------------------------


  • Pulse — (malloc_seq_num > delay && malloc_seq_num <= delay + duration), delay duration .


<--- delay --->
--------------+                +------------------------------
              |                |
              |                | All further allocations pass
              |                |
              +----------------+
              <--- duration --->


:



  • OVERTHROWER_STRATEGY
  • OVERTHROWER_SEED
  • OVERTHROWER_DUTY_CYCLE
  • OVERTHROWER_DELAY
  • OVERTHROWER_DURATION


activateOverthrower. , Overthrower , /dev/urandom.



README.md.





  • Overthrower malloc /.
  • .
  • Overthrower .
  • Overthrower .
  • Overthrower , .
  • Overthrower’ .
  • Overthrower Overthrower-aware . , .
  • Overthrower lui-même est testé sur Ubuntu (depuis 14.04) et macOS (depuis Sierra (10.12) et Xcode 8.3). Pendant les tests, Overthrower essaie de se laisser tomber, entre autres.
  • Si un véritable MOO apparaît dans le système, Overthrower fait tout son possible pour ne pas tomber.



All Articles