user4063847
user4063847

Reputation:

open() : Device or resource busy (/dev/rtc(x))

So I have an RTC hooked up on my beaglebone and it works fine through cat'ing the /sys/class/rtc/rtx(x)/time file, however my C code to monitor the time has an error I can't seem to solve.

if ((rtc_fd = open(RTC, O_RDONLY, 444)) < 0)
    REPORT_ERROR("open(RTC)");

where RTC is the path to /dev/rtc1. REPORT_ERROR is a macro function for reporting custom errors.

Anyways, I am running this code just before a for loop with 10 iterations and it is outputting to a log file. I always get the strerror(perror) message: Device or resource busy But then it still goes on to give me my 10 outputs that are correct.

I am using close() at the end as well.

What gives?

edit: Perhaps I should add that this is running in a daemonized process, and I am using iocotl() with RTC_RD_TIME during the loop.

#define REPORT_ERROR(X) do {\
        fprintf(log,"err@ "X": %s@ %s:%d\n",\
        strerror(errno), __FILE__, __LINE__ - 1);\
        exit(EXIT_FAILURE);\
        } while(0)

#define RTC "/dev/rtc1"

int main(void)
{
    int rtc_fd;
    FILE *log;
    struct rtc_time tm;

    if ((log = fopen(LOG_FILE, "a+")) == NULL)
        exit(EXIT_FAILURE);

    if ((dup2(fileno(log), STDERR_FILENO)) < 0)
        REPORT_ERROR("dup2()");

    if ((rtc_fd = open(RTC, O_RDONLY, 444)) < 0)
        REPORT_ERROR("open(RTC)");

    /* Main loop */
    for (int i = 0; i < 10; ++i)
    {
        if ((ioctl(rtc_fd, RTC_RD_TIME, &rtctime)) != 0)
            REPORT_ERROR("ioctl(rtc_fd)");

        fprintf(log, "%02d:%02d:%02.lf   %d-%d-%d\n", tm.hour, tm.minute,
                tm.second, tm.mon + 1, tm.mday, tm.year + 1900);
        sleep(1);
    }

    close(rtc_fd);
    return 0;
}

OUTPUT:

err@ open(RTC): Device or resource busy@ ha-daemon.c:80
05:06:09   2-12-2015
05:06:10   2-12-2015
05:06:11   2-12-2015
05:06:12   2-12-2015
05:06:13   2-12-2015
05:06:14   2-12-2015
05:06:15   2-12-2015
05:06:16   2-12-2015
05:06:17   2-12-2015
05:06:18   2-12-2015

Upvotes: 1

Views: 3468

Answers (1)

Edgar Bonet
Edgar Bonet

Reputation: 3566

This is not really an answer, but my edit to the question got rejected with the comment that I should post it as an answer instead. So here it goes.

The code, as posted, does not compile. I modified it minimally so that it compiles with no warnings and I can test it. Here is the list of changes. Some of them may be specific to my environment (gcc 4.8.1 / Ubuntu Linux 14.04 / x86-64):

  • added all the missing #includes
  • defined LOG_FILE, defining it as /dev/tty just makes testing easier
  • replaced /dev/rtc1 by /dev/rtc0 (I have no rtc1)
  • replaced &rtctime (the last argument of the ioctl) by &tm, otherwise it would neither make sense nor compile
  • fixed the printf format: "%02d" instead of "%02.lf"
  • put the correct names for the rtctime struct fields: tm_hour, tm_min, etc.

And here is the modified code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/rtc.h>

#define LOG_FILE "/dev/tty"

#define REPORT_ERROR(X) do {\
        fprintf(log,"err@ "X": %s@ %s:%d\n",\
        strerror(errno), __FILE__, __LINE__ - 1);\
        exit(EXIT_FAILURE);\
        } while(0)

#define RTC "/dev/rtc0"

int main(void)
{
    int rtc_fd;
    FILE *log;
    struct rtc_time tm;

    if ((log = fopen(LOG_FILE, "a+")) == NULL)
        exit(EXIT_FAILURE);

    if ((dup2(fileno(log), STDERR_FILENO)) < 0)
        REPORT_ERROR("dup2()");

    if ((rtc_fd = open(RTC, O_RDONLY, 444)) < 0)
        REPORT_ERROR("open(RTC)");

    /* Main loop */
    for (int i = 0; i < 10; ++i)
    {
        if ((ioctl(rtc_fd, RTC_RD_TIME, &tm)) != 0)
            REPORT_ERROR("ioctl(rtc_fd)");

        fprintf(log, "%02d:%02d:%02d   %d-%d-%d\n", tm.tm_hour, tm.tm_min,
                tm.tm_sec, tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900);
        sleep(1);
    }

    close(rtc_fd);
    return 0;
}

The test results: It compiles and works as expected. Either it runs with no error message, or it prints an error message and exits immediately. If one instance of the program is running, starting a second instance gives the "Device or resource busy" error message, as expected.

In other words, "works for me".

Upvotes: 1

Related Questions