Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SIGXFSZ is sent by kernel unless something is printed to stdout?

Tags:

c

linux

I am learning "Advanced Programming in Unix Environment", and have a problem with exercise no.11 in chapter 10.

In my program, I set RLIMIT_FSIZE to 1024.

So the kernel should send SIGXFSZ to my program when write trying to exceed that limit.

But I found that SIGXFSZ is not send unless something is printed to stdout.

Here is my code:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <signal.h>

#define BUFFSIZE 100

void xfsz_handler(int signo)
{
    fprintf(stderr, "%d, %s\n", signo, strsignal(signo));
}

int main(int argc, char* argv[])
{
    int n;
    char buf[BUFFSIZE];
    struct rlimit fsizeLimit;

    fsizeLimit.rlim_cur=1024;
    fsizeLimit.rlim_max=1024;
    if(setrlimit(RLIMIT_FSIZE, &fsizeLimit) < 0)
    {
        perror("setrlimit error");
        exit(-1);
    }

    if(signal(SIGXFSZ, xfsz_handler)==SIG_ERR)
    {
        fprintf(stderr, "set signal handler error for %d\n", SIGXFSZ);
        exit(-1);
    }

    printf("what ever\n"); /* we need this to get SIGXFSZ sent */


    while ( (n=read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
    {
        int byteWrite = 0;
        if ( (byteWrite = write(STDOUT_FILENO, buf, n)) < 0)
        {
            perror("write error");
            exit(-1);
        }

        if(byteWrite!=n)
        {
            fprintf(stderr, "byteWrite=%d, n=%d\n", byteWrite, n);
            exit(-1);
        }
    }

    if (n<0)
    {
        perror("read error");
        exit(-1);
    }
    return 0;
}

if I comment out the following line in the code, kernel will not transmit SIGXFSZ.

printf("What ever . . . \n");

Why this happens? Thanks in advance.

[root@luaDevelopment ex11]# ./myCopy < /root/workspace/AdvanceProgrammingInTheUnixEnvironment.20140627.tar.bz2 >aa.tar.bz2
byteWrite=24, n=100
[root@luaDevelopment ex11]# make
gcc -o myCopy myCopy.c -std=gnu99 -I../../lib/ -L../../lib/ -lch10
[root@luaDevelopment ex11]# ./myCopy < /root/workspace/AdvanceProgrammingInTheUnixEnvironment.20140627.tar.bz2 >aa.tar.bz2
byteWrite=24, n=100
25, File size limit exceeded
[root@luaDevelopment ex11]#
like image 252
user3693690 Avatar asked Jul 03 '14 06:07

user3693690


1 Answers

user3693690 found the answer in Appendix C of the book:

10.11 Under Linux 3.2.0, Mac OS X 10.6.8, and Solaris 10, the signal handler for SIGXFSZ is never called because the loop exits the program on a short write, but write returns a count of 24 as soon as the file’s size reaches 1,024 bytes. When the file’s size has reached 1,000 bytes under FreeBSD 8.0, the signal handler is called on the next attempt to write 100 bytes, and the write call returns −1 with errno set to EFBIG("File too big"). On all four platforms, if we attempt an additional write at the current file offset (the end of the file), we will receive SIGXFSZ and write will fail, returning −1 with errno set to EFBIG.

like image 58
4 revs, 3 users 75% Avatar answered Oct 16 '22 10:10

4 revs, 3 users 75%