From 000ce0cf21f0eb8eb79156efdd9df615f06ce5f5 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 12 Aug 2001 15:22:48 +0200 Subject: [PATCH] Made I/O more robust by handling EINTR --- CONTRIBUTORS | 3 +++ HISTORY | 3 ++- dvbapi.c | 29 ++++++++++++++++------------- eit.c | 6 +++--- recording.c | 8 ++++---- remote.c | 6 +++--- svdrp.c | 6 +++--- tools.c | 28 ++++++++++++++++++++++++++-- tools.h | 4 +++- 9 files changed, 63 insertions(+), 30 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index bcd6c721..241c8614 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -126,3 +126,6 @@ Matjaz Thaler Artur Skawina for improving the font file generation in the Makefile + +Werner Fink + for making I/O more robust by handling EINTR diff --git a/HISTORY b/HISTORY index 65474555..715b6682 100644 --- a/HISTORY +++ b/HISTORY @@ -622,7 +622,7 @@ Video Disk Recorder Revision History - Fixed calculating the timeout value in cFile::FileReady() (thanks to Wolfgang Henselmann-Weiss). -2001-08-11: Version 0.91 +2001-08-12: Version 0.91 - Fixed displaying colored button texts that are too long. - Suppressing replay progress display when replaying a DVD. @@ -648,3 +648,4 @@ Video Disk Recorder Revision History - Fixed displaying editing marks when toggling a mark in "pause" mode. - If there is no free DVB device to record, the log message will now be given only once. +- Made I/O more robust by handling EINTR (thanks to Werner Fink). diff --git a/dvbapi.c b/dvbapi.c index 65f7e254..4c386105 100644 --- a/dvbapi.c +++ b/dvbapi.c @@ -7,7 +7,7 @@ * DVD support initially written by Andreas Schultz * based on dvdplayer-0.5 by Matjaz Thaler * - * $Id: dvbapi.c 1.105 2001/08/11 12:21:49 kls Exp $ + * $Id: dvbapi.c 1.106 2001/08/12 15:09:42 kls Exp $ */ //#define DVDDEBUG 1 @@ -82,6 +82,8 @@ extern "C" { #define CHECK(s) { if ((s) < 0) LOG_ERROR; } // used for 'ioctl()' calls +#define FATALERRNO (errno != EAGAIN && errno != EINTR) + typedef unsigned char uchar; const char *IndexToHMSF(int Index, bool WithFrame) @@ -158,7 +160,7 @@ cIndexFile::cIndexFile(const char *FileName, bool Record) if (index) { f = open(fileName, O_RDONLY); if (f >= 0) { - if ((int)read(f, index, buf.st_size) != buf.st_size) { + if ((int)safe_read(f, index, buf.st_size) != buf.st_size) { esyslog(LOG_ERR, "ERROR: can't read from file '%s'", fileName); delete index; index = NULL; @@ -222,7 +224,7 @@ bool cIndexFile::CatchUp(void) int offset = (last + 1) * sizeof(tIndex); int delta = (newLast - last) * sizeof(tIndex); if (lseek(f, offset, SEEK_SET) == offset) { - if (read(f, &index[last + 1], delta) != delta) { + if (safe_read(f, &index[last + 1], delta) != delta) { esyslog(LOG_ERR, "ERROR: can't read from index"); delete index; index = NULL; @@ -249,7 +251,7 @@ void cIndexFile::Write(uchar PictureType, uchar FileNumber, int FileOffset) { if (f >= 0) { tIndex i = { FileOffset, PictureType, FileNumber, 0 }; - if (write(f, &i, sizeof(i)) != sizeof(i)) { + if (safe_write(f, &i, sizeof(i)) != sizeof(i)) { esyslog(LOG_ERR, "ERROR: can't write to index file"); close(f); f = -1; @@ -542,7 +544,7 @@ void cRecordBuffer::Input(void) t = time(NULL); } else if (r < 0) { - if (errno != EAGAIN) { + if (FATALERRNO) { LOG_ERROR; if (errno != EBUFFEROVERFLOW) break; @@ -569,8 +571,9 @@ void cRecordBuffer::Output(void) int r = 0; for (;;) { int g = Get(b + r, sizeof(b) - r); - if (g > 0) { + if (g > 0) r += g; + if (r > 0) { int Count = r, Result; const uchar *p = remux.Process(b, Count, Result, &pictureType); if (p) { @@ -580,7 +583,7 @@ void cRecordBuffer::Output(void) if (index && pictureType != NO_PICTURE) index->Write(pictureType, fileName.Number(), fileSize); while (Result > 0) { - int w = write(recordFile, p, Result); + int w = safe_write(recordFile, p, Result); if (w < 0) { LOG_ERROR_STR(fileName.Name()); recording = false; @@ -619,7 +622,7 @@ int ReadFrame(int f, uchar *b, int Length, int Max) esyslog(LOG_ERR, "ERROR: frame larger than buffer (%d > %d)", Length, Max); Length = Max; } - int r = read(f, b, Length); + int r = safe_read(f, b, Length); if (r < 0) LOG_ERROR; return r; @@ -705,7 +708,7 @@ void cPlayBuffer::Output(void) p += w; r -= w; } - else if (w < 0 && errno != EAGAIN) { + else if (w < 0 && FATALERRNO) { LOG_ERROR; Stop(); return; @@ -922,7 +925,7 @@ void cReplayBuffer::Input(void) } else if (r == 0) eof = true; - else if (r < 0 && errno != EAGAIN) { + else if (r < 0 && FATALERRNO) { LOG_ERROR; break; } @@ -2071,7 +2074,7 @@ void cTransferBuffer::Input(void) } } else if (r < 0) { - if (errno != EAGAIN) { + if (FATALERRNO) { LOG_ERROR; if (errno != EBUFFEROVERFLOW) break; @@ -2105,7 +2108,7 @@ void cTransferBuffer::Output(void) p += w; r -= w; } - else if (w < 0 && errno != EAGAIN) { + else if (w < 0 && FATALERRNO) { LOG_ERROR; Stop(); return; @@ -2214,7 +2217,7 @@ void cCuttingBuffer::Action(void) } LastIFrame = 0; } - write(toFile, buffer, Length); + safe_write(toFile, buffer, Length); toIndex->Write(PictureType, toFileName->Number(), FileSize); FileSize += Length; if (!LastIFrame) diff --git a/eit.c b/eit.c index 6584e598..14738f3b 100644 --- a/eit.c +++ b/eit.c @@ -13,7 +13,7 @@ * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * $Id: eit.c 1.18 2001/08/11 14:51:28 kls Exp $ + * $Id: eit.c 1.19 2001/08/12 15:04:37 kls Exp $ ***************************************************************************/ #include "eit.h" @@ -1229,11 +1229,11 @@ void cSIProcessor::Action() { /* read section */ unsigned char buf[4096+1]; // max. allowed size for any EIT section (+1 for safety ;-) - if (read(filters[a].handle, buf, 3) == 3) + if (safe_read(filters[a].handle, buf, 3) == 3) { int seclen = ((buf[1] & 0x0F) << 8) | (buf[2] & 0xFF); int pid = filters[a].pid; - int n = read(filters[a].handle, buf + 3, seclen); + int n = safe_read(filters[a].handle, buf + 3, seclen); if (n == seclen) { seclen += 3; diff --git a/recording.c b/recording.c index ddca1a4b..0190d108 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.c 1.32 2001/06/16 10:33:20 kls Exp $ + * $Id: recording.c 1.33 2001/08/12 15:09:59 kls Exp $ */ #define _GNU_SOURCE @@ -141,7 +141,7 @@ int cResumeFile::Read(void) if (fileName) { int f = open(fileName, O_RDONLY); if (f >= 0) { - if (read(f, &resume, sizeof(resume)) != sizeof(resume)) { + if (safe_read(f, &resume, sizeof(resume)) != sizeof(resume)) { resume = -1; LOG_ERROR_STR(fileName); } @@ -158,7 +158,7 @@ bool cResumeFile::Save(int Index) if (fileName) { int f = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (f >= 0) { - if (write(f, &Index, sizeof(Index)) != sizeof(Index)) + if (safe_write(f, &Index, sizeof(Index)) != sizeof(Index)) LOG_ERROR_STR(fileName); close(f); return true; @@ -243,7 +243,7 @@ cRecording::cRecording(const char *FileName) int size = buf.st_size; summary = new char[size + 1]; // +1 for terminating 0 if (summary) { - int rbytes = read(f, summary, size); + int rbytes = safe_read(f, summary, size); if (rbytes >= 0) { summary[rbytes] = 0; if (rbytes != size) diff --git a/remote.c b/remote.c index db8fa870..eed91105 100644 --- a/remote.c +++ b/remote.c @@ -6,7 +6,7 @@ * * Ported to LIRC by Carsten Koch 2000-06-16. * - * $Id: remote.c 1.23 2001/07/27 10:17:19 kls Exp $ + * $Id: remote.c 1.24 2001/08/12 15:07:26 kls Exp $ */ #include "remote.h" @@ -199,7 +199,7 @@ int cRcIoRCU::ReceiveByte(int TimeoutMs) // Returns the byte if one was received within a timeout, -1 otherwise if (cFile::FileReady(f, TimeoutMs)) { unsigned char b; - if (read(f, &b, 1) == 1) + if (safe_read(f, &b, 1) == 1) return b; else LOG_ERROR; @@ -436,7 +436,7 @@ void cRcIoLIRC::Action(void) LOCK_THREAD; - if (cFile::FileReady(f, REPEATLIMIT) && read(f, buf, sizeof(buf)) > 21) { + if (cFile::FileReady(f, REPEATLIMIT) && safe_read(f, buf, sizeof(buf)) > 21) { if (!receivedData) { // only accept new data the previous data has been fetched int count; sscanf(buf, "%*x %x %29s", &count, LastKeyName); // '29' in '%29s' is LIRC_KEY_BUF-1! diff --git a/svdrp.c b/svdrp.c index a626fdad..d3bceec1 100644 --- a/svdrp.c +++ b/svdrp.c @@ -10,7 +10,7 @@ * and interact with the Video Disk Recorder - or write a full featured * graphical interface that sits on top of an SVDRP connection. * - * $Id: svdrp.c 1.20 2001/07/22 13:58:48 kls Exp $ + * $Id: svdrp.c 1.21 2001/08/12 15:10:16 kls Exp $ */ #define _GNU_SOURCE @@ -264,7 +264,7 @@ bool cSVDRP::Send(const char *s, int length) { if (length < 0) length = strlen(s); - int wbytes = write(file, s, length); + int wbytes = safe_write(file, s, length); if (wbytes == length) return true; if (wbytes < 0) { @@ -920,7 +920,7 @@ void cSVDRP::Process(void) lastActivity = time(NULL); if (file.Ready(false)) { unsigned char c; - int r = read(file, &c, 1); + int r = safe_read(file, &c, 1); if (r > 0) { if (c == '\n' || c == 0x00) { // strip trailing whitespace: diff --git a/tools.c b/tools.c index 75e96487..e6aba17a 100644 --- a/tools.c +++ b/tools.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 1.38 2001/08/11 14:49:48 kls Exp $ + * $Id: tools.c 1.39 2001/08/12 15:12:54 kls Exp $ */ #define _GNU_SOURCE @@ -23,9 +23,33 @@ int SysLogLevel = 3; +ssize_t safe_read(int filedes, void *buffer, size_t size) +{ + for (;;) { + ssize_t p = read(filedes, buffer, size); + if (p < 0 && errno == EINTR) { + dsyslog(LOG_INFO, "EINTR while reading from file handle %d - retrying", filedes); + continue; + } + return p; + } +} + +ssize_t safe_write(int filedes, const void *buffer, size_t size) +{ + for (;;) { + ssize_t p = write(filedes, buffer, size); + if (p < 0 && errno == EINTR) { + dsyslog(LOG_INFO, "EINTR while writing to file handle %d - retrying", filedes); + continue; + } + return p; + } +} + void writechar(int filedes, char c) { - write(filedes, &c, sizeof(c)); + safe_write(filedes, &c, sizeof(c)); } char *readline(FILE *f) diff --git a/tools.h b/tools.h index 6baaff30..bf2e46b5 100644 --- a/tools.h +++ b/tools.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.h 1.27 2001/08/11 09:52:14 kls Exp $ + * $Id: tools.h 1.28 2001/08/12 15:13:02 kls Exp $ */ #ifndef __TOOLS_H @@ -33,6 +33,8 @@ extern int SysLogLevel; template inline void swap(T &a, T &b) { T t = a; a = b; b = t; }; +ssize_t safe_read(int filedes, void *buffer, size_t size); +ssize_t safe_write(int filedes, const void *buffer, size_t size); void writechar(int filedes, char c); char *readline(FILE *f); char *strn0cpy(char *dest, const char *src, size_t n);