summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrubidium42 <rubidium@openttd.org>2021-05-13 10:00:41 +0200
committerrubidium42 <rubidium42@users.noreply.github.com>2021-05-14 23:22:29 +0200
commitaa5a8fe28a224fd581b6053e4a5ce38f3e1a9694 (patch)
tree3641fec62fd2f0969ce0ac06b4f7670d7e43c9f4 /src
parent297d6e20bf0467d2a42e49bee291829ce3bb7c58 (diff)
downloadopenttd-aa5a8fe28a224fd581b6053e4a5ce38f3e1a9694.tar.xz
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.
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/console_cmds.cpp9
-rw-r--r--src/crashlog.cpp6
-rw-r--r--src/debug.cpp5
-rw-r--r--src/newgrf_profiling.cpp6
-rw-r--r--src/stdafx.h3
-rw-r--r--src/walltime_func.h80
7 files changed, 94 insertions, 16 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2d4fffc8c..801a92cb3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -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
diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp
index a417831cb..39a52f0b5 100644
--- a/src/console_cmds.cpp
+++ b/src/console_cmds.cpp
@@ -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;
}
diff --git a/src/crashlog.cpp b/src/crashlog.cpp
index c447019fe..c69dddef8 100644
--- a/src/crashlog.cpp
+++ b/src/crashlog.cpp
@@ -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 *buffer, const char *last) const
*/
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);
diff --git a/src/debug.cpp b/src/debug.cpp
index 25a0f1a82..39c695e03 100644
--- a/src/debug.cpp
+++ b/src/debug.cpp
@@ -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';
}
diff --git a/src/newgrf_profiling.cpp b/src/newgrf_profiling.cpp
index 8ec8cff54..27a1bc80e 100644
--- a/src/newgrf_profiling.cpp
+++ b/src/newgrf_profiling.cpp
@@ -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));
diff --git a/src/stdafx.h b/src/stdafx.h
index 937c053f2..319d94edf 100644
--- a/src/stdafx.h
+++ b/src/stdafx.h
@@ -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 */
diff --git a/src/walltime_func.h b/src/walltime_func.h
new file mode 100644
index 000000000..219a8907d
--- /dev/null
+++ b/src/walltime_func.h
@@ -0,0 +1,80 @@
+/*
+ * 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