Программа виснет. (С)

Модератор: Модераторы разделов

Аватара пользователя
fatboy
Сообщения: 156
ОС: Zenwalk Linux, Windows XP

Программа виснет.

Сообщение fatboy »

Уважаемые посетители форума, подскажите пожалуйста где может быть ошибка в нижеприведенном коде. Я знаю что там много ненадежного и не очень эфективного кода, но я уже полторы недели в очень плотном графике бъюсь с различными ошибками сегментации, логическими ошибками и разными нюансами работы системных вызовов! Ошибка может быть очень тривиальной, но у меня уже нет нервов ее выискивать, а отложить это на потом нет возможности... Руки опускаются, и я вынужден просить совета...

Есть функции:

Код: Выделить всё

int openInFile( const char *fileName ){
    int inFD;
#ifdef _DEBUG_
    printf("DEBUG : openInFile : Opening file %s\n", fileName);
#endif
    if( inFD = open( fileName, 0 ) == -1 ){
        if( errno == ENOENT ){ // a source file DNE
            write( 1, "The file to be backed up, ", 26 );
            write( 1, fileName, strlen( fileName ) );
            write( 1, ", does not exist.\n", 18 );
        }else{ // other error
            perror( "open inFD" );
        } // if eith
    }
    return inFD; // returns either > 0 in case of success, or -1 in case of error.
}

int openOutFile( const char *fileName, int flags ){
#ifdef _DEBUG_
    printf("DEBUG : openOutFile : Opening file %s\n", fileName);
#endif
    int outFD;
    if( ( outFD = open( fileName, flags ) ) == -1 ){
        if( errno == EEXIST ){ // usually, a path DNE
            write( 1, "The backup already contains a file named ", 41 );
            write( 1, fileName, strlen( fileName ) );
            write( 1, "\n", 1 );
        }else{ // other error
            perror( "open outFD" );
        }
    }
    return outFD; // returns either > 0 in case of success, or -1 in case of error.
}

int fcp( int inFileDescr, int outFileDescr ){
#ifdef _DEBUG_
    printf("DEBUG : fcp : copying file");
#endif
    char buf[IO_BUF_SIZE];
    int n = 0;
    while( ( n = read( inFileDescr, buf, IO_BUF_SIZE ) ) > 0 ){
#ifdef _DEBUG_
        printf("DEBUG : fcp : %d characters read", n);
#endif
        write( outFileDescr, buf, n );
    }
    if( n == -1 ){
        perror( "fcp : read()" );
    }
    return n;
}

int setFilePerm( int protoFileDescr, int targetFileDescr, const char *destName ){
    struct stat srcStat;
    if( fstat( protoFileDescr, &srcStat ) == 0 ){
        if( fchmod( targetFileDescr, srcStat.st_mode ) == 0 ){
            return 1;
        }
    }
    write( 1, "Permissions have not been set for file ", 38 );
    write( 1, destName, strlen( destName ) );
    write( 1, "\n", 1 );
    return -1;
}

int copyFile( const char *src, const char *dest, const char *spoint, const char *pathBranch, int destFlags ){
    int inFD, outFD;

    if( ( inFD = openInFile( src ) == -1 ) ){
        return -1;
    }
    buildDirTree( spoint, pathBranch );
#ifdef _DEBUG_
    printf("DEBUG : copyFile : Tree built\n");
#endif
    if( ( outFD = openOutFile( dest, destFlags ) ) == -1 ){
        close( inFD );
        return -1;
    }
#ifdef _DEBUG_
    printf("DEBUG : copyFile : outFD opened\n");
#endif
    if( fcp( inFD, outFD ) == -1 ){
        return -1;
    }
#ifdef _DEBUG_
    printf("DEBUG : copyFile : file copied\n");
#endif
    if( setFilePerm( inFD, outFD, dest ) == -1 ){
        close( inFD );
        close( outFD );
        return -1;
    }
#ifdef _DEBUG_
    printf("DEBUG : copyFile : Permissions set\n");
#endif
    close( inFD );
    close( outFD );
#ifdef    _DEBUG_
    printf("DEBUG : copyFile : Descriptors closed\n");
#endif
    return 0;
}


вызываются они вот так:

Код: Выделить всё

void rs( char *file ){
#ifdef _DEBUG_
    printf( "rs : %s\n", file );
#endif
    struct sepPath sp;
    struct stat buf;
    char *sourceFile = (char *)calloc( strlen( backupDir ) + strlen( file ), sizeof( char ) );
    strcat( sourceFile, backupDir );
    strcat( sourceFile, file );
    tf = malloc( strlen( sourceFile ) );
    strcpy( tf, sourceFile );

    splitPath( file, &sp );

    if( stat( sourceFile, &buf ) == -1 ){
        if( errno == ENOENT ){
            write( 1, "The backup does not contain the file, ", 38 );
            write( 1, sourceFile, strlen(sourceFile) );
            write( 1, ", to be restored.\n", 18 );
        }else{
            perror( "stat : rs" );
        }
        return;
    }

    if( S_ISREG( buf.st_mode ) ){
        /* previous version. DO NOT DELETE UNTIL NEW ONE IS FULLY TESTED */
        /********************************************************************************/
        //if( copyFile( sourceFile, file, sp.dirName, O_CREAT|O_WRONLY|O_TRUNC ) == -1 ){
        /********************************************************************************/
        if( copyFile( sourceFile, file, "/", sp.dirName, O_CREAT|O_WRONLY|O_TRUNC  ) == -1 ){
            write( 1, "File ", 5 );
            write( 1, sourceFile, strlen( sourceFile ) );
            write( 1, " has not been restored due to an internal error.\n", 48 );
            perror( "rs : copyFile" );
        }
    }else if( S_ISDIR( buf.st_mode ) ){
        // copyDir( sourceFile, file, sp.dirName );
        dirsFIFO = (char**)malloc( sizeof( char * ) );
        ftw( tf, fillDirFIFO, 8 ); // 1st pass. Fill a dirsFIFO, do nothing to reg files.
        // build a directory tree
        int i = 0;
        for( i; i < dirsFound - 1; i++ ){
            char *dir = (char *)( dirsFIFO[i] + strlen( backupDir ) );
#ifdef _DEBUG_
            printf( "DEBUG : rs : dir == %s\n", dir );
#endif
            mkdir( dir, 0755 );
            //free( dir );
            free( dirsFIFO[i] );
        }
        free( dirsFIFO[i] );
        free( dirsFIFO );
        ftw( tf, restoreRegs, 8 ); // second pass. Restore all reg files.
    }
    free( tf );
    free( sourceFile );
    dirsFound = 1;
} // end of rs()


С включенной _DEBUG_ получается такой вывод:

Код: Выделить всё

guest[~]$ ./bush
DEBUG : main : backDir/tmp
DEBUG : main : innitialization passed.
db == /tmp
DEBUG : main : getenv("HOME") == /tmp
DEBUG : main : backupDir == /tmp/backup
bush: rs /tmp/saad/A/x.file
DEBUG : components == 2
DEBUG :    components[0] == rs
rs : /tmp/saad/A/x.file
DEBUG : openInFile : Opening file /tmp/backup/tmp/saad/A/x.file
DEBUG : buildDirTree : start point : /
DEBUG : buildDirTree : path : /tmp/saad/A
DEBUG : buildDirTree : realloc (2) passed
DEBUG : buildDirTree : Fuction finished.
DEBUG : copyFile : Tree built
DEBUG : openOutFile : Opening file /tmp/saad/A/x.file
DEBUG : copyFile : outFD opened

.......... тут программа висит ...............


А дальше она просто виснет.
Zenwalk 4.0
TOSHIBA Satellite A100
Спасибо сказали:
Аватара пользователя
Mage-Warrior
Сообщения: 869
Статус: Семь раз понюхай, один раз откуси!
ОС: SlackWare 12.1

Re: Программа виснет.

Сообщение Mage-Warrior »

Если честно, то не силен в С :blush: . Но могу посоветовать запустить прогу с strace ($strace myprog). Будет видно, на вызове какой системной функции присходит "зависание".
*- Большинство проблем, дружок, завсегда покажет лог! -*
Спасибо сказали:
Аватара пользователя
nesk
Сообщения: 2268
Статус: Линукссаксовец
ОС: MS Windows XP Home SP3

Re: Программа виснет.

Сообщение nesk »

Mage-Warrior писал(а):
06.08.2008 11:00
Если честно, то не силен в С :blush: . Но могу посоветовать запустить прогу с strace ($strace myprog). Будет видно, на вызове какой системной функции присходит "зависание".

+1

и еще пару советов
отладочные сообщения лучше выводить в stderr
frpintf(stderr,"DEBUG : ....
потому как поток stderr не буферезируется
и еще, что значит виснет.
Это слово не о чём не говорит. Это может быть зацикливания, или действительно вечное ожидание.
У вас там никаких спец файлов не копируется типа: каналов, сокетов, файлов устройств?
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.

0xDEFEC8ED
Спасибо сказали:
Аватара пользователя
fatboy
Сообщения: 156
ОС: Zenwalk Linux, Windows XP

Re: Программа виснет.

Сообщение fatboy »

OK, спасибо, попробую с strace.

Спец. файлов нет.

Если бы я знал что происходит когда она висит, то проблемы скорее всего уже не было бы :). Если она зацикливается то, наверное, в fcp(){... while( n = read()){...} ... }, явных циклов больше нигде нет.
Zenwalk 4.0
TOSHIBA Satellite A100
Спасибо сказали:
Аватара пользователя
nesk
Сообщения: 2268
Статус: Линукссаксовец
ОС: MS Windows XP Home SP3

Re: Программа виснет.

Сообщение nesk »

fatboy писал(а):
06.08.2008 14:23
OK, спасибо, попробую с strace.

если не поможет - то gdb :blush:

А вообще хотелось бы глянуть хотя бы ps -l (что бы хотя бы посмотреть что делает процесс.)
Если б она зациклилась в read в fcp, то мы бы на экране выдели бы кучу строк
printf("DEBUG : fcp : %d characters read", n);
write( outFileDescr, buf, n );
Внимание: У меня под рукой нет машины с Linux. Я не использую эту ОС. Ответы я даю либо по памяти, либо мне помогает гугл. Тщательно читайте маны по тем командам и конфигурационным файлам, которые я упоминаю.

0xDEFEC8ED
Спасибо сказали:
Аватара пользователя
fatboy
Сообщения: 156
ОС: Zenwalk Linux, Windows XP

Re: Программа виснет.

Сообщение fatboy »

Значит, проблема решена :) :laugh:

strace очень помог, как и использование fprintf(). Оказалось что в openInFile() я не правильно поставил скобки:

Код: Выделить всё

if( inFD = open( fileName, 0 ) == -1 ){

таким образом, присваивая булево значение инту (но в С это ОК). Т.е. при удачном открытии файла inFD становился == 0.
Такую же ошибку я допустил и в copyFile():

Код: Выделить всё

if( ( inFD = openInFile( src ) == -1 ) ){

А функция fcp не висела на самом деле а ждала ввода с inFD == 0, т.е. со стандартного ввода.
Вот так я прошляпил.

Огромное всем спасибо за советы, мне они ОЧЕНЬ помогли.
Zenwalk 4.0
TOSHIBA Satellite A100
Спасибо сказали:
Sleeping Daemon
Сообщения: 1450

Re: Программа виснет.

Сообщение Sleeping Daemon »

fatboy писал(а):
06.08.2008 14:23
OK, спасибо, попробую с strace.

Спец. файлов нет.

Если бы я знал что происходит когда она висит, то проблемы скорее всего уже не было бы :). Если она зацикливается то, наверное, в fcp(){... while( n = read()){...} ... }, явных циклов больше нигде нет.

IO_BUF_SIZE где опредена?
Спасибо сказали: