This change fixes potential problems with static values returned by
functions that are not thread-safe (filenames of score cache files
and score tape filenames, which change with each invocation of these
functions). Additionally, more problems can (and likely will) happen
with using global variables (score data of last added score entry),
which are changed in the main process while the thread function is
using them.
To fix this, all relevant data is copied to a structure which is then
exclusively used by the corresponding thread function.
static void DownloadServerScoreToCacheExt(struct HttpRequest *request,
struct HttpResponse *response,
static void DownloadServerScoreToCacheExt(struct HttpRequest *request,
struct HttpResponse *response,
+ int level_nr,
+ char *score_cache_filename)
{
request->hostname = setup.api_server_hostname;
request->port = API_SERVER_PORT;
{
request->hostname = setup.api_server_hostname;
request->port = API_SERVER_PORT;
" \"levelset_identifier\": \"%s\",\n"
" \"level_nr\": \"%d\"\n"
"}\n",
" \"levelset_identifier\": \"%s\",\n"
" \"level_nr\": \"%d\"\n"
"}\n",
- levelset.identifier, nr);
+ levelset.identifier, level_nr);
ConvertHttpRequestBodyToServerEncoding(request);
ConvertHttpRequestBodyToServerEncoding(request);
ConvertHttpResponseBodyToClientEncoding(response);
ConvertHttpResponseBodyToClientEncoding(response);
- char *filename = getScoreCacheFilename(nr);
+ char *filename = score_cache_filename;
server_scores.updated = TRUE;
}
server_scores.updated = TRUE;
}
-static void DownloadServerScoreToCache(int nr)
+static void DownloadServerScoreToCache(int level_nr, char *score_cache_filename)
{
struct HttpRequest *request = checked_calloc(sizeof(struct HttpRequest));
struct HttpResponse *response = checked_calloc(sizeof(struct HttpResponse));
{
struct HttpRequest *request = checked_calloc(sizeof(struct HttpRequest));
struct HttpResponse *response = checked_calloc(sizeof(struct HttpResponse));
- DownloadServerScoreToCacheExt(request, response, nr);
+ DownloadServerScoreToCacheExt(request, response,
+ level_nr, score_cache_filename);
checked_free(request);
checked_free(response);
checked_free(request);
checked_free(response);
struct DownloadServerScoreToCacheThreadData
{
int level_nr;
struct DownloadServerScoreToCacheThreadData
{
int level_nr;
+ char *score_cache_filename;
};
static int DownloadServerScoreToCacheThread(void *data_raw)
{
struct DownloadServerScoreToCacheThreadData *data = data_raw;
};
static int DownloadServerScoreToCacheThread(void *data_raw)
{
struct DownloadServerScoreToCacheThreadData *data = data_raw;
- DownloadServerScoreToCache(data->level_nr);
+ DownloadServerScoreToCache(data->level_nr,
+ data->score_cache_filename);
static void DownloadServerScoreToCacheAsThread(int nr)
{
static struct DownloadServerScoreToCacheThreadData data;
static void DownloadServerScoreToCacheAsThread(int nr)
{
static struct DownloadServerScoreToCacheThreadData data;
+ char *score_cache_filename = getScoreCacheFilename(nr);
+
+ checked_free(data.score_cache_filename);
+ data.score_cache_filename = getStringCopy(score_cache_filename);
ExecuteAsThread(DownloadServerScoreToCacheThread,
"DownloadServerScoreToCache", &data,
ExecuteAsThread(DownloadServerScoreToCacheThread,
"DownloadServerScoreToCache", &data,
static void UploadScoreToServerExt(struct HttpRequest *request,
struct HttpResponse *response,
static void UploadScoreToServerExt(struct HttpRequest *request,
struct HttpResponse *response,
+ int level_nr,
+ char *score_tape_filename,
+ struct ScoreEntry *score_entry)
- struct ScoreEntry *score_entry = &scores.entry[scores.last_added];
-
request->hostname = setup.api_server_hostname;
request->port = API_SERVER_PORT;
request->method = API_SERVER_METHOD;
request->uri = API_SERVER_URI_ADD;
request->hostname = setup.api_server_hostname;
request->port = API_SERVER_PORT;
request->method = API_SERVER_METHOD;
request->uri = API_SERVER_URI_ADD;
- char *tape_filename = getScoreTapeFilename(score_entry->tape_basename, nr);
- char *tape_base64 = get_file_base64(tape_filename);
+ char *tape_base64 = get_file_base64(score_tape_filename);
if (tape_base64 == NULL)
{
if (tape_base64 == NULL)
{
levelset_author,
leveldir_current->levels,
leveldir_current->first_level,
levelset_author,
leveldir_current->levels,
leveldir_current->first_level,
level_name,
level_author,
level.rate_time_over_score,
level_name,
level_author,
level.rate_time_over_score,
-static void UploadScoreToServer(int nr)
+static void UploadScoreToServer(int level_nr, char *score_tape_filename,
+ struct ScoreEntry *score_entry)
{
struct HttpRequest *request = checked_calloc(sizeof(struct HttpRequest));
struct HttpResponse *response = checked_calloc(sizeof(struct HttpResponse));
{
struct HttpRequest *request = checked_calloc(sizeof(struct HttpRequest));
struct HttpResponse *response = checked_calloc(sizeof(struct HttpResponse));
- UploadScoreToServerExt(request, response, nr);
+ UploadScoreToServerExt(request, response,
+ level_nr, score_tape_filename, score_entry);
checked_free(request);
checked_free(response);
checked_free(request);
checked_free(response);
struct UploadScoreToServerThreadData
{
int level_nr;
struct UploadScoreToServerThreadData
{
int level_nr;
+ char *score_tape_filename;
+ struct ScoreEntry score_entry;
};
static int UploadScoreToServerThread(void *data_raw)
{
struct UploadScoreToServerThreadData *data = data_raw;
};
static int UploadScoreToServerThread(void *data_raw)
{
struct UploadScoreToServerThreadData *data = data_raw;
- UploadScoreToServer(data->level_nr);
+ UploadScoreToServer(data->level_nr,
+ data->score_tape_filename,
+ &data->score_entry);
static void UploadScoreToServerAsThread(int nr)
{
static struct UploadScoreToServerThreadData data;
static void UploadScoreToServerAsThread(int nr)
{
static struct UploadScoreToServerThreadData data;
+ struct ScoreEntry *score_entry = &scores.entry[scores.last_added];
+ char *score_tape_filename = getScoreTapeFilename(score_entry->tape_basename, nr);
+
+ checked_free(data.score_tape_filename);
+ data.score_entry = *score_entry;
+ data.score_tape_filename = getStringCopy(score_tape_filename);
ExecuteAsThread(UploadScoreToServerThread,
"UploadScoreToServer", &data,
ExecuteAsThread(UploadScoreToServerThread,
"UploadScoreToServer", &data,