Skip to content

Commit f8352de

Browse files
authored
Linux fixes (#7)
* fixing app memory & boot time calculation * fixed error event, fixed procstat reading * compilation error in getSysMemoryUsage * static member definition * connection status for linux * missing include * removed const * fixed compilation errors * include path for uuid on linux * added STDLIB guid to avoid dependencies * link with standard library for linux * updated cmake for linux * updated cmake for linux * getConnection for linux
1 parent 224f6b7 commit f8352de

File tree

4 files changed

+197
-42
lines changed

4 files changed

+197
-42
lines changed

CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,12 @@ elseif(APPLE)
165165
create_source_groups(MACOS_SOURCES)
166166

167167
elseif(LINUX)
168-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGUID_LIBUUID")
168+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGUID_STDLIB -std=c++17")
169+
170+
if(CLANG)
171+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
172+
endif()
173+
169174
endif()
170175

171176
if(${GA_BUILD_SAMPLE})

sample/CMakeLists.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,16 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/Release")
55
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/Debug")
66
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/Release")
77

8-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -stdlib=libc++")
8+
set(CMAKE_CXX_STANDARD 17)
9+
10+
if(LINUX)
11+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
12+
13+
if(CLANG)
14+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
15+
endif()
16+
17+
endif()
918

1019
set(GA_ROOT_DIR "..")
1120

source/dependencies/crossguid/guid.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ THE SOFTWARE.
4242
#include <cassert>
4343
#endif
4444

45+
#ifdef GUID_STDLIB
46+
#include <random>
47+
#include <vector>
48+
#include <string>
49+
#endif
50+
4551
BEGIN_XG_NAMESPACE
4652

4753
#ifdef GUID_ANDROID
@@ -279,6 +285,53 @@ Guid newGuid()
279285
}
280286
#endif
281287

288+
#ifdef GUID_STDLIB
289+
unsigned char random_char()
290+
{
291+
std::random_device rd;
292+
std::mt19937 gen(rd());
293+
std::uniform_int_distribution<> dis(0,255);
294+
return static_cast<unsigned char>(dis(gen));
295+
}
296+
297+
void generate_hex(size_t len, std::vector<char>& out)
298+
{
299+
for(size_t i = 0; i < len; ++i)
300+
{
301+
const auto rc = random_char();
302+
char s[3];
303+
snprintf(s, 3, "%02x", int(rc));
304+
305+
out.push_back(s[0]);
306+
out.push_back(s[1]);
307+
}
308+
}
309+
310+
Guid newGuid()
311+
{
312+
std::vector<char> result;
313+
generate_hex(4, result);
314+
result.push_back('-');
315+
generate_hex(2, result);
316+
result.push_back('-');
317+
generate_hex(2, result);
318+
result.push_back('-');
319+
generate_hex(2, result);
320+
result.push_back('-');
321+
generate_hex(4, result);
322+
result.push_back('\0');
323+
324+
std::array<unsigned char, 16> data;
325+
const int size = std::min<int>(16, result.size());
326+
for(int i = 0; i < size; ++i)
327+
{
328+
data[i] = result[i];
329+
}
330+
331+
return Guid(std::move(data));
332+
}
333+
#endif
334+
282335
// this is the mac and ios version
283336
#ifdef GUID_CFUUID
284337
Guid newGuid()
@@ -400,4 +453,4 @@ namespace std
400453
{
401454
lhs.swap(rhs);
402455
}
403-
}
456+
}

source/gameanalytics/Platform/GALinux.cpp

Lines changed: 127 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,71 @@
44

55
#include "GAState.h"
66

7+
#include <errno.h>
8+
#include <linux/unistd.h>
9+
#include <linux/kernel.h>
710
#include <execinfo.h>
811
#include <sys/utsname.h>
912
#include <sys/stat.h>
1013
#include <unistd.h>
1114
#include <sys/sysinfo.h>
15+
#include <sys/ioctl.h>
16+
#include <sys/socket.h>
17+
#include <linux/wireless.h>
18+
#include <ifaddrs.h>
19+
20+
struct sigaction gameanalytics::GAPlatformLinux::prevSigAction;
21+
22+
struct ProcessStat
23+
{
24+
int pid;
25+
std::string comm;
26+
char state;
27+
long ppid;
28+
long pgrp;
29+
long session;
30+
long tty_nr;
31+
long tpgid;
32+
unsigned long flags;
33+
unsigned long minflt;
34+
unsigned long cminflt;
35+
unsigned long majflt;
36+
unsigned long cmajflt;
37+
unsigned long utime;
38+
unsigned long stime;
39+
long cutime;
40+
long cstime;
41+
long priority;
42+
long nice;
43+
long num_threads;
44+
long itrealvalue;
45+
long starttime;
46+
long vsize;
47+
long rss;
48+
};
49+
50+
ProcessStat readProcessStat()
51+
{
52+
ProcessStat stat{};
53+
std::ifstream statFile("/proc/self/stat");
54+
55+
if (!statFile.is_open())
56+
{
57+
return {};
58+
}
59+
60+
std::string line;
61+
std::getline(statFile, line);
62+
std::istringstream iss(line);
63+
64+
iss >> stat.pid >> stat.comm >> stat.state >> stat.ppid >> stat.pgrp >> stat.session
65+
>> stat.tty_nr >> stat.tpgid >> stat.flags >> stat.minflt >> stat.cminflt
66+
>> stat.majflt >> stat.cmajflt >> stat.utime >> stat.stime
67+
>> stat.cutime >> stat.cstime >> stat.priority >> stat.nice
68+
>> stat.num_threads >> stat.itrealvalue >> stat.starttime >> stat.vsize >> stat.rss;
69+
70+
return stat;
71+
}
1272

1373
std::string gameanalytics::GAPlatformLinux::getOSVersion()
1474
{
@@ -156,7 +216,7 @@ void gameanalytics::GAPlatformLinux::signalHandler(int sig, siginfo_t* info, voi
156216
if (errorCount <= MAX_ERROR_TYPE_COUNT)
157217
{
158218
errorCount++;
159-
events::GAEvents::addErrorEvent(EGAErrorSeverity::Critical, stackTrace, {}, false, false);
219+
events::GAEvents::addErrorEvent(EGAErrorSeverity::Critical, stackTrace, "", -1, {}, false, false);
160220
events::GAEvents::processEvents("error", false);
161221
}
162222

@@ -180,6 +240,51 @@ std::string gameanalytics::GAPlatformLinux::getCpuModel() const
180240
return systemInfo.machine;
181241
}
182242

243+
std::string gameanalytics::GAPlatformLinux::getConnectionType()
244+
{
245+
struct ifaddrs* list = nullptr;
246+
struct ifaddrs* current = nullptr;
247+
248+
std::string connection = CONNECTION_OFFLINE;
249+
250+
if(getifaddrs(&list) == -1)
251+
{
252+
return connection;
253+
}
254+
255+
current = list;
256+
while(current)
257+
{
258+
int sock = -1;
259+
if (!current->ifa_addr || current->ifa_addr->sa_family != AF_PACKET)
260+
{
261+
struct iwreq req = {};
262+
strncpy(req.ifr_name, current->ifa_name, IFNAMSIZ);
263+
264+
int sock = socket(AF_INET, SOCK_STREAM, 0);
265+
if (sock == -1)
266+
{
267+
connection = CONNECTION_LAN;
268+
}
269+
else
270+
{
271+
if (ioctl(sock, SIOCGIWNAME, &req) != -1)
272+
{
273+
connection = CONNECTION_WIFI;
274+
}
275+
}
276+
}
277+
278+
if(sock != -1)
279+
close(sock);
280+
281+
current = current->ifa_next;
282+
}
283+
284+
freeifaddrs(list);
285+
return connection;
286+
}
287+
183288
std::string gameanalytics::GAPlatformLinux::getGpuModel() const
184289
{
185290
return UNKNOWN_VALUE;
@@ -203,59 +308,42 @@ int64_t gameanalytics::GAPlatformLinux::getTotalDeviceMemory() const
203308

204309
int64_t gameanalytics::GAPlatformLinux::getAppMemoryUsage() const
205310
{
206-
struct task_basic_info info;
207-
208-
mach_msg_type_number_t infoSize = TASK_BASIC_INFO_COUNT;
209-
kern_return_t result = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &infoSize);
210-
211-
if(result == KERN_SUCCESS)
212-
{
213-
return utilities::convertBytesToMB(info.resident_size);
214-
}
311+
constexpr int k_pageSize = 1024;
312+
ProcessStat proc = readProcessStat();
215313

216-
return 0;
314+
int64_t vmUsage = proc.vsize / k_pageSize;
315+
int64_t resident = proc.rss * (sysconf(_SC_PAGE_SIZE) / k_pageSize);
316+
317+
int64_t inBytes = (vmUsage + resident) * 1024;
318+
319+
return utilities::convertBytesToMB(inBytes);
217320
}
218321

219322
int64_t gameanalytics::GAPlatformLinux::getSysMemoryUsage() const
220323
{
221-
mach_port_t port = mach_host_self();
222-
mach_msg_type_number_t hostSize = sizeof(vm_statistics_data_t) / sizeof(integer_t);
223-
224-
vm_size_t pageSize;
225-
host_page_size(port, &pageSize);
226-
227-
vm_statistics_data_t stats;
228-
229-
if(host_statistics(port, HOST_VM_INFO, (host_info_t)&stats, &hostSize) == KERN_SUCCESS)
324+
struct sysinfo info = {};
325+
if(sysinfo(&info) == 0)
230326
{
231-
const int64_t freeMemory = (stats.free_count + stats.inactive_count) * pageSize;
232-
return getTotalDeviceMemory() - utilities::convertBytesToMB(freeMemory);
327+
return utilities::convertBytesToMB(info.totalram - info.freeram);
233328
}
234329

235330
return 0;
236331
}
237332

238333
int64_t gameanalytics::GAPlatformLinux::getBootTime() const
239334
{
240-
const size_t len = 4;
241-
int mib[len] = {0,0,0,0};
242-
struct kinfo_proc kp = {};
335+
ProcessStat procStat = readProcessStat();
243336

244-
const size_t pidId = 3;
245-
246-
size_t num = len;
247-
sysctlnametomib("kern.proc.pid", mib, &num);
248-
mib[pidId] = getpid();
249-
250-
num = sizeof(kp);
251-
sysctl(mib, len, &kp, &num, NULL, 0);
337+
struct sysinfo info = {};
338+
if(sysinfo(&info) != 0)
339+
{
340+
return 0;
341+
}
252342

253-
struct timeval startTime = kp.kp_proc.p_un.__p_starttime;
254-
struct timeval currentTime = {};
255-
256-
gettimeofday(&currentTime, NULL);
257-
258-
return currentTime.tv_sec - startTime.tv_sec;
343+
int64_t startTime = procStat.starttime / sysconf(_SC_CLK_TCK);
344+
int64_t bootTime = info.uptime - startTime;
345+
346+
return bootTime;
259347
}
260348

261349
#endif

0 commit comments

Comments
 (0)