Fix MQTT client ID collision on ARM 32-bit userland with 64-bit kernel

The MQTT client ID was generated using sprintf with %ld and time(nullptr).
On platforms with 32-bit userland but 64-bit kernel (such as Raspberry Pi OS
and some custom Alpine Linux builds), time_t is a 64-bit long long but %ld
only reads 32 bits. Since the upper 32 bits of the current Unix timestamp
are zero, this always produces "MMDVMHost.0", causing client ID collisions
when multiple instances or restarts occur.

Replace time()-based client IDs with PID-based IDs using getpid(), which is
always a 32-bit value and unique per process. Platform-guarded for Windows
(_getpid) and POSIX (getpid).
This commit is contained in:
Andy Taylor 2026-03-08 12:49:26 +00:00
parent f2c45f2ae5
commit 8efcac05e6

View file

@ -21,7 +21,12 @@
#include <cassert>
#include <cstdio>
#include <cstring>
#include <ctime>
#if defined(_WIN32) || defined(_WIN64)
#include <process.h>
#else
#include <unistd.h>
#endif
CMQTTConnection::CMQTTConnection(const std::string& host, unsigned short port, const std::string& name, const bool authEnabled, const std::string& username, const std::string& password, const std::vector<std::pair<std::string, void (*)(const unsigned char*, unsigned int)>>& subs, unsigned int keepalive, MQTT_QOS qos) :
@ -53,7 +58,11 @@ CMQTTConnection::~CMQTTConnection()
bool CMQTTConnection::open()
{
char name[50U];
::sprintf(name, "MMDVMHost.%ld", ::time(nullptr));
#if defined(_WIN32) || defined(_WIN64)
::sprintf(name, "MMDVMHost.%u", (unsigned)::_getpid());
#else
::sprintf(name, "MMDVMHost.%u", (unsigned)::getpid());
#endif
::fprintf(stdout, "MMDVMHost (%s) connecting to MQTT as %s\n", m_name.c_str(), name);