Внимательно присмотритесь как к собственным, так и к библиотечным функциям, которыми вы пользуетесь. Нереентерабельным является код, манипулирующий переменными, объявленными вне локальной области видимости, например глобальными или статическими. Любая функция, в которой используется статическая переменная, реентерабельной не является. Хотя применение глобальных переменных вообще осуждается, поскольку усложняет сопровождение программы, но сами по себе они еще не создают гонок. Следующее, на что надо обратить внимание, – это бесконтрольное изменение таких переменных. Например, статический член класса в С++ разделяется всеми экземплярами класса и, следовательно, оказывается глобальной переменной. Если этот член инициализируется в момент первого обращения к классу, а затем только читается, то ничего страшного не случится. Если же некоторая переменная обновляется, то необходимо ставить замки, чтобы обновление не осуществлялось одновременно разными частями программы. Особое внимание следует обращать на обработчики сигналов, поскольку они могут оказаться нереентерабельными, даже если для остальной программы эта проблема не актуальна.

Внимательно изучите код обработчиков сигналов, в частности те данные, которыми они манипулируют.

Следующий случай – это внешние процессы, которые могут прерывать вашу программу. Тщательно изучите места, где файлы или каталоги создаются в общедоступных областях, обращайте внимание на предсказуемость имен.

Найдите все случаи создания файлов (к примеру, временных) в разделяемых каталогах (/tmp или /usr/tmp в UNIX, \Windows\temp в Windows). При создании такого файла библиотечной функцией ореп() надо указывать флаг 0_EXCL (или его эквивалент), а если он создается функцией CreateFile() -флаг CREATE_NEW. В этом случае вызов завершится неудачно, если файл с указанным именем уже существует. Поместите обращения к этим функциям в цикл, который будет пробовать новые случайные имена, пока не создаст файл. Если имя выбирается действительно случайно (следите, чтобы имя файла содержало только допустимые в вашей системе символы), то почти наверняка потребуется только одна итерация. К сожалению, функция fopen() из стандартной библиотеки С не позволяет указать флаг 0_EXCL, поэтому применяйте функцию ореп() с последующим преобразованием возвращенного дескриптора в указатель FILE*. В операционных системах Microsoft системные вызовы типа CreateFile не только более гибки, но и работают быстрее. Никогда не полагайтесь на функции, подобные mktemp(3), поскольку они создают предсказуемые имена файлов; противник может создать файл точно с таким же именем. В командных интерпретаторах UNIX нет встроенных операций для создания имен временных файлов, а конструкции типа Is > / tmp/ list. $ $ способствуют возникновению гонки. Поэтому в shell–сценариях нужно пользоваться функцией mktemp(l).