Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declared with attribute warn_unused_result [-Wunused-result]

Tags:

c

I compiled the code below using Ideone.com and the following warning popped up.

rtctimer.c: In function 'rtctimer_next_tick':
rtctimer.c:87.7: warning: ignoring return value of 'read', 
                 declared with attribute warn_unused_result [-Wunused-result]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <poll.h>
#include <sched.h>
#include <fcntl.h>
#include <math.h>
#include <sys/ioctl.h>
#include <linux/rtc.h>
#include "rtctimer.h"

struct rtctimer_s
{
    int rtc_fd;
    int current_hz;
    int rtc_running;
    int verbose;
    int usecs;
};

rtctimer_t *rtctimer_new( int verbose )
{
    rtctimer_t *rtctimer = malloc( sizeof( rtctimer_t ) );
    if( !rtctimer ) return 0;

    rtctimer->verbose = verbose;
    if( (( rtctimer->rtc_fd = open( "/dev/rtc", O_RDONLY ) ) < 0) ) {
        if( rtctimer->verbose ) {
            fprintf( stderr, "rtctimer: Cannot open /dev/rtc: %s\n",
                     strerror( errno ) );
        }
        if( ( rtctimer->rtc_fd = open( "/dev/misc/rtc", O_RDONLY ) ) < 0 ) {
            if( rtctimer->verbose ) {
                fprintf( stderr, "rtctimer: Cannot open /dev/misc/rtc: %s\n",
                         strerror( errno ) );
            }
            free( rtctimer );
            return 0;
        }
    }

    if( fcntl( rtctimer->rtc_fd, F_SETOWN, getpid() ) < 0 ) {
        if( rtctimer->verbose ) {
            fprintf( stderr, "rtctimer: Cannot set ownership of "
                             "/dev/rtc: %s\n", strerror( errno ) );
        }
        close( rtctimer->rtc_fd );
        free( rtctimer );
        return 0;
    }

    rtctimer->rtc_running = 0;
    rtctimer->current_hz = 0;
    rtctimer->usecs = 0;
    return rtctimer;
}

void rtctimer_delete( rtctimer_t *rtctimer )
{
    rtctimer_stop_clock( rtctimer );
    close( rtctimer->rtc_fd );
    free( rtctimer );
}

int rtctimer_next_tick( rtctimer_t *rtctimer )
{
    unsigned long rtc_data;
    struct pollfd pfd;
    pfd.fd = rtctimer->rtc_fd;
    pfd.events = POLLIN | POLLERR;

again:
    if( poll( &pfd, 1, 100000 ) < 0 ) {
        if( errno == EINTR ) {
            goto again;
        }

        if( rtctimer->verbose ) {
            fprintf( stderr, "rtctimer: poll call failed: %s\n",
                     strerror( errno ) );
        }
        return 0;
    }

    read( rtctimer->rtc_fd, &rtc_data, sizeof( rtc_data ) );
    return 1;
}

int rtctimer_set_interval( rtctimer_t *rtctimer, int hz )
{
    int restart;

    if( hz == rtctimer->current_hz ) {
        return 1;
    }

    restart = rtctimer_stop_clock( rtctimer );

    if( ioctl( rtctimer->rtc_fd, RTC_IRQP_SET, hz ) < 0 ) {
        if( rtctimer->verbose ) {
            fprintf( stderr, "rtctimer: Cannot set periodic interval: %s\n",
                     strerror( errno ) );
        }
        return 0;
    }

    rtctimer->current_hz = hz;
    rtctimer->usecs = (int) ( ( ( 1000.0 * 1000.0 ) / hz ) + 0.5 );

    if( restart ) {
        rtctimer_start_clock( rtctimer );
    }

    return 1;
}

int rtctimer_start_clock( rtctimer_t *rtctimer )
{
    if( !rtctimer->rtc_running ) {
        if( ioctl( rtctimer->rtc_fd, RTC_PIE_ON, 0 ) < 0 ) {
            if( rtctimer->verbose ) {
                fprintf( stderr, "rtctimer: Cannot start periodic "
                         "interrupts: %s\n", strerror( errno ) );
            }
            return 0;
        }
        rtctimer->rtc_running = 1;
    }
    return rtctimer->rtc_running;
}

int rtctimer_stop_clock( rtctimer_t *rtctimer )
{
    int was_running = rtctimer->rtc_running;

    if( rtctimer->rtc_running ) {
        if( ioctl( rtctimer->rtc_fd, RTC_PIE_OFF, 0 ) < 0 ) {
            if( rtctimer->verbose ) {
                fprintf( stderr, "rtctimer: Cannot stop periodic "
                         "interrupts: %s\n", strerror( errno ) );
            }
            return rtctimer->rtc_running;
        }
        rtctimer->rtc_running = 0;
    }

    return was_running;
}

int rtctimer_get_resolution( rtctimer_t *rtctimer )
{
    return rtctimer->current_hz;
}

int rtctimer_get_usecs( rtctimer_t *rtctimer )
{
    return rtctimer->usecs;
}

int set_realtime_priority( int max )
{
    struct sched_param schp;

    memset( &schp, 0, sizeof( schp ) );
    if( max ) schp.sched_priority = sched_get_priority_max( SCHED_FIFO );
    else schp.sched_priority = sched_get_priority_max( SCHED_FIFO ) - 1;

    if( sched_setscheduler( 0, SCHED_FIFO, &schp ) != 0 ) {
        return 0;
    }

    return 1;
}

int set_default_priority( void )
{
    struct sched_param schp;

    memset( &schp, 0, sizeof( schp ) );
    schp.sched_priority = 0;
    if( sched_setscheduler( 0, SCHED_OTHER, &schp ) != 0 ) {
        return 0;
    }

    return 1;
}

What did I do wrong?

like image 501
geo Avatar asked Feb 05 '12 09:02

geo


3 Answers

read() returns a value indicating the number of bytes that it read. The warning is indicating that the code is ignoring that. You should check the return value of read() to ensure it was successful otherwise you are assuming that rtc_data has been correctly populated and it may not have been.

like image 156
hmjd Avatar answered Oct 08 '22 21:10

hmjd


You're not checking the return value of read, which is a bug just waiting to happen.

ssize_t r = read(rtctimer->rtc_fd, &rtc_data, sizeof( rtc_data ) );
if (r == -1) {
   // deal with failed read
} else if (r != sizeof(rtc_data)) {
   // you didn't read as much as you wanted to
...

If you don't check what read returns, chances are very high that your program will fail unexpectedly if a read error does occur, and it will be impossible to debug. (The second case might not apply in this specific example, or for some pipe reads.)

Always check the return value of library calls, especially I/O ones since they do fail in normal circumstances.

like image 38
Mat Avatar answered Oct 08 '22 22:10

Mat


The line

  read( rtctimer->rtc_fd, &rtc_data, sizeof( rtc_data ) );

produces a result (return value of read()), you don't use it in any way, this will get you a warning. That's the purpose of -Wunused-result.

Ignoring the return value of read() usually is a very bad idea!

like image 1
Mithrandir Avatar answered Oct 08 '22 22:10

Mithrandir