Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] thread safe tools.c




This is a patch to add thread safe functins to tools.c
Serveral other functions in vdr and (that's the problem)
plugins uses some of those return "static". 
So the entire patches maybe to long to post?


Of course the non"_r" counter parts will become superflous,
so a rename is not required.
But removing them now would cause serveral plugins not
to compile anymore.

I have not checked if all those functions are really called 
in two threads at the same time, so the plugins may run
without patching (at least mostly, because the problematic
timing windows are usually very small, not reproducible, 
and the side effects may not cause segfaults.).

I think "AddDir" maybe very critical as it is used by many plugins
and VDR is not using it only while in init, AFAS.

So sorry for the non developers:
This will not be the last patch to make vdr thread proof.



I have patched the caller modules to use the new functions
and found no new problems generated, but 4..10 eyes may see more ;-)



# diff -Naur ../vdr-1.3.17.vanilla/tools.h tools.h
--- ../vdr-1.3.17.vanilla/tools.h       Sun Oct 31 17:16:37 2004
+++ tools.h     Tue Dec  7 23:51:19 2004
@@ -59,6 +59,7 @@
 ssize_t safe_write(int filedes, const void *buffer, size_t size);
 void writechar(int filedes, char c);
 char *readline(FILE *f);
+char *readline_r(FILE *f, char * buffer, size_t size );
 char *strcpyrealloc(char *dest, const char *src);
 char *strn0cpy(char *dest, const char *src, size_t n);
 char *strreplace(char *s, char c1, char c2);
@@ -66,7 +67,8 @@
 char *skipspace(const char *s);
 char *stripspace(char *s);
 char *compactspace(char *s);
-const char *strescape(const char *s, const char *chars); ///< \warning returns a statically allocated string
!
+const char *strescape(const char *s, const char *chars); ///< \warning DON'T USE returns a statically alloca
ted string!
+const char *strescape_r(const char *s, const char *chars, char ** buf);
 bool startswith(const char *s, const char *p);
 bool endswith(const char *s, const char *p);
 bool isempty(const char *s);
@@ -75,7 +77,9 @@
 void delay_ms(int ms);
 bool isnumber(const char *s);
 const char *itoa(int n); ///< \warning returns a statically allocated string!
+char *itoa_r(int n, char * buffer, size_t);
 const char *AddDirectory(const char *DirName, const char *FileName); ///< \warning returns a statically allo
cated string!
+const char *AddDirectory_r(const char *DirName, const char *FileName, char **buf);
 int FreeDiskSpaceMB(const char *Directory, int *UsedMB = NULL);
 bool DirectoryOk(const char *DirName, bool LogErrors = false);
 bool MakeDirs(const char *FileName, bool IsDirectory = false);
@@ -87,6 +91,10 @@
 const char *WeekDayName(int WeekDay); ///< \warning returns a statically allocated string!
 const char *WeekDayName(time_t t); ///< \warning returns a statically allocated string!
 const char *DayDateTime(time_t t = 0); ///< \warning returns a statically allocated string!
+
+const char *WeekDayName_r(int WeekDay, char buffer[4]);
+const char *WeekDayName_r(time_t t, char buffer [4]);
+const char *DayDateTime_r(time_t t = 0, char buffer[32]=NULL);

 class cPoller {
 private:


# diff -Naur ../vdr-1.3.17.vanilla/tools.c tools.c
--- ../vdr-1.3.17.vanilla/tools.c       Sun Nov 21 15:36:34 2004
+++ tools.c     Wed Dec  8 00:08:41 2004
@@ -65,7 +65,7 @@
   safe_write(filedes, &c, sizeof(c));
 }

-char *readline(FILE *f)
+char *readline(FILE *f) // DON'T USE IN MULTITHREAD, use readline_r instead!
 {
   static char buffer[MAXPARSEBUFFER];
   if (fgets(buffer, sizeof(buffer), f) > 0) {
@@ -77,6 +77,20 @@
   return NULL;
 }

+char *readline_r(FILE *f, char * buffer, size_t size )
+{
+  if ((buffer==NULL)||(size==0)) return NULL;
+  if (fgets(buffer, size, f) > 0) {
+     int l = strlen(buffer) - 1;
+     if (l >= 0 && buffer[l] == '\n')
+        buffer[l] = 0;
+     return buffer;
+     }
+  return NULL;
+}
+
+
+
 char *strcpyrealloc(char *dest, const char *src)
 {
   if (src) {
@@ -167,7 +181,7 @@
   return s;
 }

-const char *strescape(const char *s, const char *chars)
+const char *strescape(const char *s, const char *chars)// NOT THREAD SAFE, DON'T USE THIS!
 {
   static char *buffer = NULL;
   const char *p = s;
@@ -190,6 +204,33 @@
   return s;
 }

+const char *strescape_r(const char *s, const char *escapechars, char ** dest)
+// Abstract: Precedes each char listed in "escapechars" with a "\"
+// *dest must point to NULL or to malloced memory.
+// The caller must call free(dest)!
+{
+  const char *p = s;
+  char *t = NULL;
+
+  if (s==NULL) return s;
+  while (*p) {
+        if (strchr(escapechars, *p)) {
+           if (t==NULL) {// we may need some more memory
+              *dest = (char *)realloc(*dest, 2 * strlen(s) + 1);// worstcase string doubles length
+              t = *dest + (p - s);     // Move Tmp point to end of current string in dest
+              s = strcpy(*dest, s);    // set to new buffer
+              }
+           *t++ = '\\';                        // insert a "\"
+           }
+        if (t)                         // if we have a new buffer store old char
+           *t++ = *p;
+        p++;
+        }
+  if (t)
+     *t = 0;
+  return s;
+}
+
 bool startswith(const char *s, const char *p)
 {
   while (*p) {
@@ -222,7 +263,7 @@
   return strlen(buf);
 }

-int time_ms(void)
+int time_ms(void) // thread safe when called from init() the first time.
 {
   static time_t t0 = 0;
   struct timeval t;
@@ -253,14 +294,29 @@
   return true;
 }

-const char *itoa(int n)
+const char *itoa(int n)// USE itoa_r
 {
   static char buf[16];
   snprintf(buf, sizeof(buf), "%d", n);
   return buf;
 }

-const char *AddDirectory(const char *DirName, const char *FileName)
+
+char *itoa_r(int n, char * buf, size_t size)
+{
+  if ((buf!=NULL)&&(size!=0))
+     snprintf(buf, size, "%d", n);
+  else
+     return NULL;
+  return buf;
+}
+
+
+
+// file and directory helper
+
+
+const char *AddDirectory(const char *DirName, const char *FileName) // DONT'T USE IN THREADS
 {
   static char *buf = NULL;
   free(buf);
@@ -268,6 +324,13 @@
   return buf;
 }

+const char *AddDirectory_r(const char *DirName, const char *FileName, char **buf)
+{
+  free(*buf);
+  asprintf(buf, "%s/%s", DirName && *DirName ? DirName : ".", FileName);
+  return *buf;
+}
+
 int FreeDiskSpaceMB(const char *Directory, int *UsedMB)
 {
   if (UsedMB)
@@ -449,9 +512,10 @@
   return TargetName ? strdup(TargetName) : NULL;
 }

+
 bool SpinUpDisk(const char *FileName)
 {
-  static char *buf = NULL;
+  char *buf = NULL;
   for (int n = 0; n < 10; n++) {
       free(buf);
       if (DirectoryOk(FileName))
@@ -468,19 +532,28 @@
             system("sync");
             remove(buf);
             gettimeofday(&tp2, NULL);
-            double seconds = (((long long)tp2.tv_sec * 1000000 + tp2.tv_usec) - ((long long)tp1.tv_sec * 100
0000 + tp1.tv_usec)) / 1000000.0;
+            double seconds = (((long long)tp2.tv_sec * 1000000 + tp2.tv_usec) - ((long long)tp1.tv_sec * 100
0000 + tp1
+.tv_usec)) / 1000000.0;
             if (seconds > 0.5)
                dsyslog("SpinUpDisk took %.2f seconds\n", seconds);
+            free(buf);
             return true;
             }
          else
             LOG_ERROR_STR(buf);
          }
       }
+  free(buf);
   esyslog("ERROR: SpinUpDisk failed");
   return false;
 }

+
+
+
+
+// time helper
+
 time_t LastModifiedTime(const char *FileName)
 {
   struct stat fs;
@@ -489,7 +562,8 @@
   return 0;
 }

-const char *WeekDayName(int WeekDay)
+
+const char *WeekDayName(int WeekDay) // DON'T USE, NOT THEAD SAFE
 {
   static char buffer[4];
   WeekDay = WeekDay == 0 ? 6 : WeekDay - 1; // we start with monday==0!
@@ -503,20 +577,56 @@
      return "???";
 }

-const char *WeekDayName(time_t t)
+const char *WeekDayName_r(int WeekDay, char buffer[4])
+{
+  if (buffer==NULL) return "???"; //=============================>>>>>
+  WeekDay = WeekDay == 0 ? 6 : WeekDay - 1; // we start with monday==0!
+  if (0 <= WeekDay && WeekDay <= 6) {
+     const char *day = tr("MonTueWedThuFriSatSun");
+     day += WeekDay * 3;
+     strncpy(buffer, day, 3);
+     return buffer;
+     }
+  else
+     return "???";
+}
+
+
+const char *WeekDayName(time_t t) // DON'T USE, NOT THEAD SAFE
 {
   struct tm tm_r;
   return WeekDayName(localtime_r(&t, &tm_r)->tm_wday);
 }

-const char *DayDateTime(time_t t)
+const char *WeekDayName_r(time_t t, char buffer[4]) // DON'T USE, NOT THEAD SAFE
+{
+  struct tm tm_r;
+  return WeekDayName_r(localtime_r(&t, &tm_r)->tm_wday,buffer);
+}
+
+
+const char *DayDateTime(time_t t) // DON'T USE, NOT THEAD SAFE
 {
   static char buffer[32];
   if (t == 0)
      time(&t);
   struct tm tm_r;
   tm *tm = localtime_r(&t, &tm_r);
-  snprintf(buffer, sizeof(buffer), "%s %2d.%02d %02d:%02d", WeekDayName(tm->tm_wday), tm->tm_mday, tm->tm_mo
n + 1, tm->tm_hour, tm->tm_min);
+  snprintf(buffer, sizeof(buffer), "%s %2d.%02d %02d:%02d"
+         , WeekDayName(tm->tm_wday), tm->tm_mday, tm->tm_mon + 1, tm->tm_hour, tm->tm_min);
+  return buffer;
+}
+
+const char *DayDateTime_r(time_t t, char buffer[32])
+{
+  if (buffer==NULL) return buffer; //=======>>>>
+  if (t == 0)
+     time(&t);
+  struct tm tm_r;
+  tm *tm = localtime_r(&t, &tm_r);
+  char tmp[4];
+  snprintf(buffer, sizeof(buffer), "%s %2d.%02d %02d:%02d"
+         , WeekDayName_r(tm->tm_wday, tmp), tm->tm_mday, tm->tm_mon + 1, tm->tm_hour, tm->tm_min);
   return buffer;
 }

Rainer





Home | Main Index | Thread Index