Changeset - r25479:5d0b41ec5e3a
[Not reviewed]
master
0 6 1
rubidium42 - 3 years ago 2021-05-13 08:00:41
rubidium@openttd.org
Codechange: use thread safe time functions

Functions like localtime, gmtime and asctime are not thread safe as they (might) reuse the same buffer. So use the safer _s/_r variant for localtime and gmtime, and use strftime in favour of asctime.
7 files changed with 94 insertions and 16 deletions:
0 comments (0 inline, 0 general)
src/CMakeLists.txt
Show inline comments
 
@@ -467,6 +467,7 @@ add_files(
 
    viewport_type.h
 
    void_cmd.cpp
 
    void_map.h
 
    walltime_func.h
 
    water.h
 
    water_cmd.cpp
 
    water_map.h
src/console_cmds.cpp
Show inline comments
 
@@ -41,7 +41,7 @@
 
#include "rail.h"
 
#include "game/game.hpp"
 
#include "table/strings.h"
 
#include <time.h>
 
#include "walltime_func.h"
 

	
 
#include "safeguards.h"
 

	
 
@@ -1369,10 +1369,9 @@ DEF_CONSOLE_CMD(ConGetSysDate)
 
		return true;
 
	}
 

	
 
	time_t t;
 
	time(&t);
 
	auto timeinfo = localtime(&t);
 
	IConsolePrintF(CC_DEFAULT, "System Date: %04d-%02d-%02d %02d:%02d:%02d", timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);
 
	char buffer[lengthof("2000-01-02 03:04:05")];
 
	LocalTime::Format(buffer, lastof(buffer), "%Y-%m-%d %H:%M:%S");
 
	IConsolePrintF(CC_DEFAULT, "System Date: %s", buffer);
 
	return true;
 
}
 

	
src/crashlog.cpp
Show inline comments
 
@@ -32,8 +32,7 @@
 
#include "game/game_info.hpp"
 
#include "company_base.h"
 
#include "company_func.h"
 

	
 
#include <time.h>
 
#include "walltime_func.h"
 

	
 
#ifdef WITH_ALLEGRO
 
#	include <allegro.h>
 
@@ -333,9 +332,8 @@ char *CrashLog::LogRecentNews(char *buff
 
 */
 
char *CrashLog::FillCrashLog(char *buffer, const char *last) const
 
{
 
	time_t cur_time = time(nullptr);
 
	buffer += seprintf(buffer, last, "*** OpenTTD Crash Report ***\n\n");
 
	buffer += seprintf(buffer, last, "Crash at: %s", asctime(gmtime(&cur_time)));
 
	buffer += UTCTime::Format(buffer, last, "Crash at: %Y-%m-%d %H:%M:%S (UTC)\n");
 

	
 
	YearMonthDay ymd;
 
	ConvertDateToYMD(_date, &ymd);
src/debug.cpp
Show inline comments
 
@@ -19,7 +19,7 @@
 
#include "os/windows/win32.h"
 
#endif
 

	
 
#include <time.h>
 
#include "walltime_func.h"
 

	
 
#include "network/network_admin.h"
 
SOCKET _debug_socket = INVALID_SOCKET;
 
@@ -248,8 +248,7 @@ const char *GetLogPrefix()
 
{
 
	static char _log_prefix[24];
 
	if (_settings_client.gui.show_date_in_logs) {
 
		time_t cur_time = time(nullptr);
 
		strftime(_log_prefix, sizeof(_log_prefix), "[%Y-%m-%d %H:%M:%S] ", localtime(&cur_time));
 
		LocalTime::Format(_log_prefix, lastof(_log_prefix), "[%Y-%m-%d %H:%M:%S] ");
 
	} else {
 
		*_log_prefix = '\0';
 
	}
src/newgrf_profiling.cpp
Show inline comments
 
@@ -13,9 +13,9 @@
 
#include "string_func.h"
 
#include "console_func.h"
 
#include "spritecache.h"
 
#include "walltime_func.h"
 

	
 
#include <chrono>
 
#include <time.h>
 

	
 

	
 
std::vector<NewGRFProfiler> _newgrf_profilers;
 
@@ -130,10 +130,8 @@ void NewGRFProfiler::Abort()
 
 */
 
std::string NewGRFProfiler::GetOutputFilename() const
 
{
 
	time_t write_time = time(nullptr);
 

	
 
	char timestamp[16] = {};
 
	strftime(timestamp, lengthof(timestamp), "%Y%m%d-%H%M", localtime(&write_time));
 
	LocalTime::Format(timestamp, lastof(timestamp), "%Y%m%d-%H%M");
 

	
 
	char filepath[MAX_PATH] = {};
 
	seprintf(filepath, lastof(filepath), "%sgrfprofile-%s-%08X.csv", FiosGetScreenshotDir(), timestamp, BSWAP32(this->grffile->grfid));
src/stdafx.h
Show inline comments
 
@@ -129,6 +129,7 @@
 
	/* Warn about functions using 'printf' format syntax. First argument determines which parameter
 
	 * is the format string, second argument is start of values passed to printf. */
 
#	define WARN_FORMAT(string, args) __attribute__ ((format (printf, string, args)))
 
#	define WARN_TIME_FORMAT(string) __attribute__ ((format (strftime, string, 0)))
 
#	if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
 
#		define FINAL final
 
#	else
 
@@ -157,6 +158,7 @@
 
#	define NORETURN
 
#	define CDECL
 
#	define WARN_FORMAT(string, args)
 
#	define WARN_TIME_FORMAT(string)
 
#	define FINAL
 
#	define FALLTHROUGH
 
#	include <malloc.h>
 
@@ -205,6 +207,7 @@
 

	
 
#	define CDECL _cdecl
 
#	define WARN_FORMAT(string, args)
 
#	define WARN_TIME_FORMAT(string)
 
#	define FINAL final
 

	
 
	/* fallthrough attribute, VS 2017 */
src/walltime_func.h
Show inline comments
 
new file 100644
 
/*
 
 * This file is part of OpenTTD.
 
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 
 * OpenTTD 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 General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 
 */
 

	
 
 /** @file walltime_func.h Functionality related to the time of the clock on your wall. */
 

	
 
#ifndef WALLTIME_FUNC_H
 
#define WALLTIME_FUNC_H
 

	
 
#include <ctime>
 

	
 
/** Helper for safely converting a std::time_t to a local time std::tm using localtime_s. */
 
struct LocalTimeToStruct {
 
	static inline std::tm ToTimeStruct(std::time_t time_since_epoch)
 
	{
 
		std::tm time = {};
 
#ifdef WIN32
 
		/* Windows has swapped the parameters around for localtime_s. */
 
		localtime_s(&time, &time_since_epoch);
 
#else
 
		localtime_r(&time_since_epoch, &time);
 
#endif
 
		return time;
 
	}
 
};
 

	
 
/** Helper for safely converting a std::time_t to a UTC time std::tm using gmtime_s. */
 
struct UTCTimeToStruct {
 
	static inline std::tm ToTimeStruct(std::time_t time_since_epoch)
 
	{
 
		std::tm time = {};
 
#ifdef WIN32
 
		/* Windows has swapped the parameters around for gmtime_s. */
 
		gmtime_s(&time, &time_since_epoch);
 
#else
 
		gmtime_r(&time_since_epoch, &time);
 
#endif
 
		return time;
 
	}
 
};
 

	
 
/**
 
 * Container for wall clock time related functionality not directly provided by C++.
 
 * @tparam T The type of the time-to-struct implementation class.
 
 */
 
template <typename T>
 
struct Time {
 
	/**
 
	 * Format the current time with the given strftime format specifiers.
 
	 * @param buffer The buffer to write the time string to.
 
	 * @param last   The last element in the buffer.
 
	 * @param format The format according to strftime format specifiers.
 
	 * @return The number of characters that were written to the buffer.
 
	 */
 
	static inline size_t Format(char *buffer, const char *last, const char *format) NOACCESS(2) WARN_TIME_FORMAT(3)
 
	{
 
		std::tm time_struct = T::ToTimeStruct(time(nullptr));
 
#ifndef _MSC_VER
 
		/* GCC bug #39438; unlike for printf where the appropriate attribute prevent the
 
		 * "format non literal" warning, that does not happen for strftime. Even though
 
		 * format warnings will be created for invalid strftime formats. */
 
#pragma GCC diagnostic push
 
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
 
#endif /* _MSC_VER */
 
		return strftime(buffer, last - buffer, format, &time_struct);
 
#ifndef _MSC_VER
 
#pragma GCC diagnostic pop
 
#endif /* _MSC_VER */
 
	}
 
};
 

	
 
/** Wall clock time functionality using the local time zone. */
 
using LocalTime = Time<LocalTimeToStruct>;
 
/** Wall clock time functionality using the UTC time zone. */
 
using UTCTime = Time<UTCTimeToStruct>;
 

	
 
#endif
0 comments (0 inline, 0 general)