Merge remote branch 'jamescoxon/master'

pull/2/head
Philip Heron 2010-04-26 14:04:37 +01:00
commit 5706271f8a
5 zmienionych plików z 112 dodań i 254 usunięć

Wyświetl plik

@ -39,7 +39,7 @@ LOCATOR_SRC = misc/locator.c
BENCHMARK_SRC = include/benchmark.h misc/benchmark.cxx
REGEX_SRC = compat/regex.h compat/regex.c
STACK_SRC = include/stack.h misc/stack.cxx
MINGW32_SRC = include/compat.h compat/getsysinfo.c compat/mingw.c compat/mingw.h compat/flock.c compat/flock.h
MINGW32_SRC = include/compat.h compat/getsysinfo.c compat/mingw.c compat/mingw.h
NLS_SRC = misc/nls.cxx
# We distribute these but do not always compile them

Wyświetl plik

@ -1,166 +0,0 @@
/* Emulate flock on platforms that lack it, primarily Windows and MinGW.
This is derived from sqlite3 sources.
http://www.sqlite.org/cvstrac/rlog?f=sqlite/src/os_win.c
http://www.sqlite.org/copyright.html
Written by Richard W.M. Jones <rjones.at.redhat.com>
(Tweaked by Daniel Richman to use as a MINGW "patch" only)
Copyright (C) 2008-2010 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <sys/file.h>
#include <stdio.h>
#include "flock.h"
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* _get_osfhandle */
#include <io.h>
/* LockFileEx */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <errno.h>
/* Determine the current size of a file. Because the other braindead
* APIs we'll call need lower/upper 32 bit pairs, keep the file size
* like that too.
*/
static BOOL
file_size (HANDLE h, DWORD * lower, DWORD * upper)
{
*lower = GetFileSize (h, upper);
return 1;
}
/* LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. */
#ifndef LOCKFILE_FAIL_IMMEDIATELY
# define LOCKFILE_FAIL_IMMEDIATELY 1
#endif
/* Acquire a lock. */
static BOOL
do_lock (HANDLE h, int non_blocking, int exclusive)
{
BOOL res;
DWORD size_lower, size_upper;
OVERLAPPED ovlp;
int flags = 0;
/* We're going to lock the whole file, so get the file size. */
res = file_size (h, &size_lower, &size_upper);
if (!res)
return 0;
/* Start offset is 0, and also zero the remaining members of this struct. */
memset (&ovlp, 0, sizeof ovlp);
if (non_blocking)
flags |= LOCKFILE_FAIL_IMMEDIATELY;
if (exclusive)
flags |= LOCKFILE_EXCLUSIVE_LOCK;
return LockFileEx (h, flags, 0, size_lower, size_upper, &ovlp);
}
/* Unlock reader or exclusive lock. */
static BOOL
do_unlock (HANDLE h)
{
int res;
DWORD size_lower, size_upper;
res = file_size (h, &size_lower, &size_upper);
if (!res)
return 0;
return UnlockFile (h, 0, 0, size_lower, size_upper);
}
/* Now our BSD-like flock operation. */
int
flock (int fd, int operation)
{
HANDLE h = (HANDLE) _get_osfhandle (fd);
DWORD res;
int non_blocking;
if (h == INVALID_HANDLE_VALUE)
{
errno = EBADF;
return -1;
}
non_blocking = operation & LOCK_NB;
operation &= ~LOCK_NB;
switch (operation)
{
case LOCK_SH:
res = do_lock (h, non_blocking, 0);
break;
case LOCK_EX:
res = do_lock (h, non_blocking, 1);
break;
case LOCK_UN:
res = do_unlock (h);
break;
default:
errno = EINVAL;
return -1;
}
/* Map Windows errors into Unix errnos. As usual MSDN fails to
* document the permissible error codes.
*/
if (!res)
{
DWORD err = GetLastError ();
switch (err)
{
/* This means someone else is holding a lock. */
case ERROR_LOCK_VIOLATION:
errno = EAGAIN;
break;
/* Out of memory. */
case ERROR_NOT_ENOUGH_MEMORY:
errno = ENOMEM;
break;
case ERROR_BAD_COMMAND:
errno = EINVAL;
break;
/* Unlikely to be other errors, but at least don't lose the
* error code.
*/
default:
fprintf(stderr, "compat_mingw_flock.c: Unknown error %i.\n", err);
errno = EIO;
}
return -1;
}
return 0;
}
#endif

Wyświetl plik

@ -1,43 +0,0 @@
/* Emulate flock on platforms that lack it, primarily Windows and MinGW.
This is derived from sqlite3 sources.
http://www.sqlite.org/cvstrac/rlog?f=sqlite/src/os_win.c
http://www.sqlite.org/copyright.html
Written by Richard W.M. Jones <rjones.at.redhat.com>
(Tweaked by Daniel Richman to use as a MINGW "patch" only)
Copyright (C) 2008-2010 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
#ifndef LOCK_SH
/* Operations for the 'flock' call (same as Linux kernel constants). */
# define LOCK_SH 1 /* Shared lock. */
# define LOCK_EX 2 /* Exclusive lock. */
# define LOCK_UN 8 /* Unlock. */
/* Can be OR'd in to one of the above. */
# define LOCK_NB 4 /* Don't block when locking. */
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
int flock (int fd, int operation);
#endif /* Windows */

Wyświetl plik

@ -32,6 +32,5 @@
#include <assert.h>
#include "compat/mingw.h"
#include "compat/flock.h"
#endif // MINGW32_H

Wyświetl plik

@ -68,7 +68,9 @@ int dl_fldigi_initialised = 0;
const char *dl_fldigi_cache_file;
struct payload *payload_list = NULL;
time_t rxTimer = 0;
pthread_mutex_t dl_fldigi_tid_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t dl_fldigi_tid_mutex;
pthread_mutex_t dl_fldigi_cache_mutex;
struct flock fl_w, fl_r, fl_u;
static void *dl_fldigi_post_thread(void *thread_argument);
static void *dl_fldigi_download_thread(void *thread_argument);
@ -78,21 +80,46 @@ static void dl_fldigi_delete_payloads();
void dl_fldigi_init()
{
CURLcode r;
CURLcode r3;
const char *home;
char *cache_file;
size_t i, fsz;
int r1, r2;
#ifdef DL_FLDIGI_DEBUG
fprintf(stderr, "dl_fldigi: dl_fldigi_init() was executed in thread %li\n", pthread_self());
#endif
/* The only thread-unsafe step of dl_fldigi. Needs to be run once, at the start, when there are no other threads. */
r = curl_global_init(CURL_GLOBAL_ALL);
/* Initialise our flock structs */
fl_w.l_whence = SEEK_SET;
fl_w.l_start = 0;
fl_w.l_len = 0;
fl_w.l_pid = getpid();
fl_r = fl_w;
fl_u = fl_w;
if (r != 0)
fl_w.l_type = F_WRLCK;
fl_r.l_type = F_RDLCK;
fl_u.l_type = F_UNLCK;
r1 = pthread_mutex_init(&dl_fldigi_tid_mutex, NULL);
if (r1 != 0)
{
fprintf(stderr, "dl_fldigi: curl_global_init failed: (%i) %s\n", r, curl_easy_strerror(r));
fprintf(stderr, "dl_fldigi: tid mutex: pthread_mutex_init failed: (%i) %s\n", r1, strerror(r1));
exit(EXIT_FAILURE);
}
r2 = pthread_mutex_init(&dl_fldigi_cache_mutex, NULL);
if (r2 != 0)
{
fprintf(stderr, "dl_fldigi: cache mutex: pthread_mutex_init failed: (%i) %s\n", r2, strerror(r2));
exit(EXIT_FAILURE);
}
r3 = curl_global_init(CURL_GLOBAL_ALL);
if (r3 != 0)
{
fprintf(stderr, "dl_fldigi: curl_global_init failed: (%i) %s\n", r3, curl_easy_strerror(r3));
exit(EXIT_FAILURE);
}
@ -151,9 +178,17 @@ void cb_dl_fldigi_toggle_dl_online()
static void put_status_safe(const char *msg, double timeout, status_timeout action)
{
int r1;
ENSURE_THREAD(DL_FLDIGI_TID);
pthread_mutex_lock(&dl_fldigi_tid_mutex);
r1 = pthread_mutex_lock(&dl_fldigi_tid_mutex);
if (r1 != 0)
{
fprintf(stderr, "dl_fldigi: tid mutex pthread_mutex_lock failed: (%i) %s\n", r1, strerror(r1));
return;
}
print_put_status(msg, timeout, action);
full_memory_barrier();
pthread_mutex_unlock(&dl_fldigi_tid_mutex);
@ -176,6 +211,7 @@ void dl_fldigi_post(const char *data, const char *identity)
pthread_t thread;
CURL *curl;
CURLcode r1, r2, r3;
int r4;
/* The first of two globals accessed by this function */
if (!dl_fldigi_initialised)
@ -317,9 +353,10 @@ void dl_fldigi_post(const char *data, const char *identity)
full_memory_barrier();
/* the 4th argument passes the thread the information it needs */
if (pthread_create(&thread, NULL, dl_fldigi_post_thread, (void *) t) != 0)
r4 = pthread_create(&thread, NULL, dl_fldigi_post_thread, (void *) t);
if (r4 != 0)
{
perror("dl_fldigi: post pthread_create");
fprintf(stderr, "dl_fldigi: post pthread_create failed: (%i) %s\n", r4, strerror(r4));
curl_easy_cleanup(curl);
return;
}
@ -333,7 +370,7 @@ static void *dl_fldigi_post_thread(void *thread_argument)
{
struct dl_fldigi_post_threadinfo *t;
t = (struct dl_fldigi_post_threadinfo *) thread_argument;
CURLcode result;
CURLcode r1;
#ifdef DL_FLDIGI_DEBUG
fprintf(stderr, "dl_fldigi: (thread %li) posting '%s'\n", pthread_self(), t->post_data);
@ -343,13 +380,13 @@ static void *dl_fldigi_post_thread(void *thread_argument)
put_status_safe("dl_fldigi: sentence uploading...", 10);
result = curl_easy_perform(t->curl);
r1 = curl_easy_perform(t->curl);
/* tests CURL-success only */
if (result == 0)
if (r1 == 0)
{
#ifdef DL_FLDIGI_DEBUG
fprintf(stderr, "dl_fldigi: (thread %li) curl result (%i) Success!\n", pthread_self(), result);
fprintf(stderr, "dl_fldigi: (thread %li) curl result (0) Success!\n", pthread_self());
#endif
put_status_safe("dl_fldigi: sentence uploaded!", 10);
@ -357,7 +394,7 @@ static void *dl_fldigi_post_thread(void *thread_argument)
else
{
#ifdef DL_FLDIGI_DEBUG
fprintf(stderr, "dl_fldigi: (thread %li) curl result (%i) %s\n", pthread_self(), result, curl_easy_strerror(result));
fprintf(stderr, "dl_fldigi: (thread %li) curl result (%i) %s\n", pthread_self(), r1, curl_easy_strerror(r1));
#endif
put_status_safe("dl_fldigi: sentence upload failed", 10);
@ -377,7 +414,8 @@ void dl_fldigi_download()
CURL *curl;
CURLcode r1, r3;
FILE *file;
int r2;
struct flock fl_wc, fl_uc;
int r2, r4;
if (!dl_fldigi_initialised)
{
@ -421,7 +459,7 @@ void dl_fldigi_download()
return;
}
file = fopen(dl_fldigi_cache_file, "w");
file = fopen(dl_fldigi_cache_file, "w+");
if (file == NULL)
{
@ -430,9 +468,10 @@ void dl_fldigi_download()
return;
}
r2 = flock(fileno(file), LOCK_EX | LOCK_NB);
fl_wc = fl_w;
r2 = fcntl(fileno(file), F_SETLK, &fl_wc);
if (r2 == EWOULDBLOCK || r2 == EAGAIN)
if (r2 == -1 && (errno == EACCES || errno == EAGAIN))
{
fprintf(stderr, "dl_fldigi: cache file is locked; not downloading\n");
curl_easy_cleanup(curl);
@ -441,7 +480,7 @@ void dl_fldigi_download()
}
else if (r2 != 0)
{
perror("dl_fldigi: flock cache file");
perror("dl_fldigi: fcntl cache file F_SETLK fl_w");
curl_easy_cleanup(curl);
fclose(file);
return;
@ -452,7 +491,8 @@ void dl_fldigi_download()
{
fprintf(stderr, "dl_fldigi: curl_easy_setopt (CURLOPT_WRITEDATA) failed: %s\n", curl_easy_strerror(r3));
curl_easy_cleanup(curl);
flock(fileno(file), LOCK_UN);
fl_uc = fl_u;
fcntl(fileno(file), F_SETLK, &fl_uc);
fclose(file);
return;
}
@ -464,10 +504,12 @@ void dl_fldigi_download()
full_memory_barrier();
/* the 4th argument passes the thread the information it needs */
if (pthread_create(&thread, NULL, dl_fldigi_download_thread, (void *) t) != 0)
r4 = pthread_create(&thread, NULL, dl_fldigi_download_thread, (void *) t);
if (r4 != 0)
{
perror("dl_fldigi: download pthread_create");
flock(fileno(file), LOCK_UN);
fprintf(stderr, "dl_fldigi: post pthread_create failed: (%i) %s\n", r4, strerror(r4));
fl_uc = fl_u;
fcntl(fileno(file), F_SETLK, &fl_uc);
fclose(file);
return;
}
@ -481,7 +523,9 @@ static void *dl_fldigi_download_thread(void *thread_argument)
{
struct dl_fldigi_download_threadinfo *t;
t = (struct dl_fldigi_download_threadinfo *) thread_argument;
CURLcode result;
CURLcode r1;
struct flock fl_rc, fl_uc;
int r2, r3;
#ifdef DL_FLDIGI_DEBUG
fprintf(stderr, "dl_fldigi: (thread %li) performing download...\n", pthread_self());
@ -491,31 +535,52 @@ static void *dl_fldigi_download_thread(void *thread_argument)
put_status_safe("dl_fldigi: payload information: downloading...", 10);
result = curl_easy_perform(t->curl);
r1 = curl_easy_perform(t->curl);
curl_easy_cleanup(t->curl);
if (result == 0)
if (r1 == 0)
{
#ifdef DL_FLDIGI_DEBUG
fprintf(stderr, "dl_fldigi: (thread %li) curl result (%i) Success!\n", pthread_self(), result);
fprintf(stderr, "dl_fldigi: (thread %li) curl result (0) Success!\n", pthread_self());
#endif
pthread_mutex_lock(&dl_fldigi_tid_mutex);
put_status("dl_fldigi: payload information: downloaded!", 10);
REQ(dl_fldigi_update_payloads);
full_memory_barrier();
pthread_mutex_unlock(&dl_fldigi_tid_mutex);
/* Swap our exclusive lock for a shared lock */
fl_rc = fl_r;
r2 = fcntl(fileno(t->file), F_SETLK, &fl_rc);
if (r2 == -1)
{
perror("dl_fldigi: failed to swap exclusive t->file lock for a shared one");
/* Really we should die fully here, because this should not happen. */
}
else
{
r3 = pthread_mutex_lock(&dl_fldigi_tid_mutex);
if (r3 != 0)
{
fprintf(stderr, "dl_fldigi: tid mutex pthread_mutex_lock failed: (%i) %s\n", r3, strerror(r3));
}
else
{
put_status("dl_fldigi: payload information: downloaded!", 10);
REQ(dl_fldigi_update_payloads);
full_memory_barrier();
pthread_mutex_unlock(&dl_fldigi_tid_mutex);
}
}
}
else
{
#ifdef DL_FLDIGI_DEBUG
fprintf(stderr, "dl_fldigi: (thread %li) curl result (%i) %s\n", pthread_self(), result, curl_easy_strerror(result));
fprintf(stderr, "dl_fldigi: (thread %li) curl result (%i) %s\n", pthread_self(), r1, curl_easy_strerror(r1));
#endif
put_status_safe("dl_fldigi: payload information: download failed", 10);
}
flock(fileno(t->file), LOCK_UN);
fl_uc = fl_u;
fcntl(fileno(t->file), F_SETLK, &fl_uc);
fclose(t->file);
free(t);
@ -567,11 +632,11 @@ static void dl_fldigi_delete_payloads()
void dl_fldigi_update_payloads()
{
FILE *file;
int r1, r_shift, r_baud;
int r1, r_shift, r_baud, i, dbfield_no;
const char *r_coding, *r_dbfield;
IrrXMLReader *xml;
struct payload *p, *n;
int i, dbfield_no;
struct flock fl_rc, fl_uc;
#ifdef DL_FLDIGI_DEBUG
fprintf(stderr, "dl_fldigi: (thread %li) attempting to update UI...\n", pthread_self());
@ -585,9 +650,9 @@ void dl_fldigi_update_payloads()
return;
}
r1 = flock(fileno(file), LOCK_SH | LOCK_NB);
if (r1 == EWOULDBLOCK || r1 == EAGAIN)
fl_rc = fl_r;
r1 = fcntl(fileno(file), F_SETLK, &fl_rc);
if (r1 == -1 && (errno == EACCES || errno == EAGAIN))
{
fprintf(stderr, "dl_fldigi: cache file is locked; not updating UI\n");
fclose(file);
@ -595,7 +660,7 @@ void dl_fldigi_update_payloads()
}
else if (r1 != 0)
{
perror("dl_fldigi: flock cache file (read)");
perror("dl_fldigi: fcntl cache file F_SETLK fl_r");
fclose(file);
return;
}
@ -611,7 +676,8 @@ void dl_fldigi_update_payloads()
if (!xml)
{
fprintf(stderr, "dl_fldigi: parsing payload info: createIrrXMLReader failed\n");
flock(fileno(file), LOCK_UN);
fl_uc = fl_u;
fcntl(fileno(file), F_SETLK, &fl_uc);
fclose(file);
return;
}
@ -633,7 +699,8 @@ void dl_fldigi_update_payloads()
fprintf(stderr, "dl_fldigi: denied %zi bytes of RAM for 'struct payload'\n", sizeof(struct payload));
dl_fldigi_delete_payloads();
delete xml;
flock(fileno(file), LOCK_UN);
fl_uc = fl_u;
fcntl(fileno(file), F_SETLK, &fl_uc);
fclose(file);
return;
}
@ -810,7 +877,8 @@ void dl_fldigi_update_payloads()
put_status("dl_fldigi: payload information loaded", 10);
delete xml;
flock(fileno(file), LOCK_UN);
fl_uc = fl_u;
fcntl(fileno(file), F_SETLK, &fl_uc);
fclose(file);
}