Проблема с gcc tracker / make / fork / exec / wait - PullRequest
0 голосов
/ 25 февраля 2010

Это наиболее необычная проблема со многими междисциплинарными последствиями.

Она фокусируется на этом фрагменте кода (имя файла mainpp.c):


#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int status;
  if (fork()) 
    {
      FILE *f=fopen("/tmp/gcc-trace","a");
      fprintf(f,"----------------------------------------------------------------\n");
      int i;
      for(i=0;i<argc;i++)
        {

          fprintf(f,"%s:",argv[i]);
        }
      wait(&status);
      fprintf(f,"\nstatus=%d",status);
      fprintf(f,"\n");
      fclose(f);
    }
  else 
    {
      execv("g++.old",argv);
    }
  sleep(10);
  return status;
}

Это используется со сценарием bash:

#!/bin/sh

gcc -g main.c -o gcc
gcc -g mainpp.c -o g++
mv /usr/bin/gcc /usr/bin/gcc.old
mv /usr/bin/g++ /usr/bin/g++.old
cp ./gcc /usr/bin/gcc
cp ./g++ /usr/bin/g++

Назначение этого кода (и соответствующего файла main.c для gcc), надеюсь, понятно.он заменяет g ++ и регистрирует вызовы g ++ плюс все аргументы командной строки, затем переходит к вызову компилятора g ++ (теперь он называется g ++. old).

Планируется использовать это для регистрации всех вызовов g ++ / gcc.(Поскольку make -n не отслеживает рекурсивные преобразования, это способ захвата вызовов «в дикой природе».)

Я опробовал это на нескольких программах, и это сработало хорошо.(Включая компиляцию самой программы.) Затем я опробовал ее на интересующем меня проекте, libapt-pkg-dev (репозиторий Ubuntu).

Сборка казалась удачной, но когда я проверял, некоторые исполняемые файлы былиотсутствует.Подсчитывая файлы в каталоге проекта, я обнаружил, что незафиксированная версия выдает 1373, тогда как зарегистрированная версия выдает 1294. Составляя список этих файлов, я обнаруживаю, что все отсутствующие файлы являются исполняемыми файлами, общими библиотеками или объектными файлами.

Получение стандарта как из зарегистрированных, так и из незарегистрированных производителей дает одинаковый результат.Записанное возвращаемое значение всех процессов, вызываемых exec, равно 0.

Я поместил спящие в различные позиции в коде.Они, кажется, не имеют никакого значения.(Код с отслеживаемой версией, кажется, компилируется намного быстрее для каждого файла. Я подозревал, что exec, возможно, вызвал завершение программы, оставляя gcc работающим. Я думал, что это может вызвать сбой, потому что некоторые объектные файлы могут не завершиться, когда другие нуждаются в них.)

У меня есть только еще одна диагностика, чтобы проверить, могу ли я диагностировать проблему, и тогда у меня нет идей.Предложения?

1 Ответ

0 голосов
/ 25 февраля 2010

Я не уверен, если это поможет решить вашу проблему, но вы рассматривали возможность использования strace вместо вашего пользовательского кода?

strace выполняет команду (или присоединяется к запущенному процессу) и перечисляет все системные вызовы, которые он выполняет. Так, например, вместо прямого запуска make вы можете выполнить:

strace -f -q -e trace=execve make
  • -f означает присоединение к новым процессам по мере их разветвления
  • -q означает запретить присоединение / отсоединение сообщений
  • -e trace=execve означает только сообщать о вызовах на execve

Затем вы можете выполнить вывод для сообщений о /usr/bin/gcc.

...