ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/utils.C
Revision: 1.110
Committed: Sat Oct 8 21:54:05 2022 UTC (19 months, 2 weeks ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.109: +11 -4 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.68 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 root 1.101 *
4 root 1.108 * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team
5 root 1.104 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
6 root 1.101 *
7 root 1.89 * Deliantra is free software: you can redistribute it and/or modify it under
8     * the terms of the Affero GNU General Public License as published by the
9     * Free Software Foundation, either version 3 of the License, or (at your
10     * option) any later version.
11 root 1.101 *
12 root 1.60 * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16 root 1.101 *
17 root 1.89 * You should have received a copy of the Affero GNU General Public License
18     * and the GNU General Public License along with this program. If not, see
19     * <http://www.gnu.org/licenses/>.
20 root 1.101 *
21 root 1.68 * The authors can be reached via e-mail to <support@deliantra.net>
22 pippijn 1.39 */
23 elmex 1.1
24     /*
25 root 1.92 * General convenience functions for deliantra.
26 elmex 1.1 */
27    
28 root 1.37 #include <cstdlib>
29     #include <sys/types.h>
30     #include <unistd.h>
31     #include <sys/time.h>
32     #include <time.h>
33     #include <signal.h>
34    
35 elmex 1.1 #include <global.h>
36     #include <material.h>
37 sf-marcmagus 1.87 #include <object.h>
38 elmex 1.1
39 root 1.79 #include <sys/time.h>
40     #include <sys/resource.h>
41    
42 root 1.4 #include <glib.h>
43    
44 root 1.63 refcnt_base::refcnt_t refcnt_dummy;
45 root 1.74 ssize_t slice_alloc;
46 root 1.40
47 sf-marcmagus 1.87 /******************************************************************************/
48    
49     /* Checks a player-provided string which will become the msg property of
50     * an object for dangerous input.
51     */
52 root 1.105 bool
53 sf-marcmagus 1.87 msg_is_safe (const char *msg)
54     {
55     bool safe = true;
56    
57     /* Trying to cheat by getting data into the object */
58 root 1.88 if (!strncmp (msg, "endmsg", sizeof ("endmsg") - 1)
59     || strstr (msg, "\nendmsg"))
60 sf-marcmagus 1.87 safe = false;
61    
62     /* Trying to make the object talk, and potentially access arbitrary code */
63     if (object::msg_has_dialogue (msg))
64     safe = false;
65    
66     return safe;
67     }
68    
69 root 1.14 /////////////////////////////////////////////////////////////////////////////
70    
71 root 1.37 void
72     fork_abort (const char *msg)
73     {
74     if (!fork ())
75     {
76 root 1.80 signal (SIGINT , SIG_IGN);
77     signal (SIGTERM, SIG_IGN);
78     signal (SIGABRT, SIG_IGN);
79 root 1.79
80 root 1.81 signal (SIGSEGV, SIG_DFL);
81 root 1.103 signal (SIGFPE , SIG_DFL);
82     #ifdef SIGBUS
83 root 1.81 signal (SIGBUS , SIG_DFL);
84 root 1.103 #endif
85 root 1.81 signal (SIGILL , SIG_DFL);
86     signal (SIGTRAP, SIG_DFL);
87    
88 root 1.52 // try to put corefiles into a subdirectory, if existing, to allow
89     // an administrator to reduce the I/O load.
90     chdir ("cores");
91 root 1.79
92     // try to detach us from as many external dependencies as possible
93     // as coredumping can take time by closing all fd's.
94     {
95     struct rlimit lim;
96    
97     if (getrlimit (RLIMIT_NOFILE, &lim))
98     lim.rlim_cur = 1024;
99    
100     for (int i = 0; i < lim.rlim_cur; ++i)
101     close (i);
102     }
103    
104 root 1.81 {
105     sigset_t empty;
106     sigemptyset (&empty);
107     sigprocmask (SIG_SETMASK, &empty, 0);
108     }
109    
110     // try to coredump with SIGTRAP
111     kill (getpid (), SIGTRAP);
112 root 1.37 abort ();
113     }
114    
115 root 1.38 LOG (llevError, "fork abort: %s\n", msg);
116 root 1.37 }
117 root 1.38
118 root 1.99 void *
119 root 1.110 salloc_ (int n) noexcept
120 root 1.10 {
121 root 1.25 void *ptr = g_slice_alloc (n);
122 root 1.13
123 root 1.110 if (ecb_expect_false (!ptr))
124     {
125     LOG (llevError, "out of memory allocating %d bytes, aborting.\n", n);
126     abort ();
127     }
128 root 1.4
129 root 1.74 slice_alloc += n;
130 root 1.23 return ptr;
131     }
132    
133 root 1.110 // thos noinline works around a bug in gcc10, which otherwise inlines
134     // this fucntion and, only in the inlined versions, optimises out
135     // the memset, leasving memory uninitialised.
136     ecb_noinline
137 root 1.99 void *
138 root 1.110 salloc_ (int n, void *src) noexcept
139 root 1.23 {
140 root 1.25 void *ptr = salloc_ (n);
141 root 1.23
142 root 1.24 if (src)
143 root 1.25 memcpy (ptr, src, n);
144 root 1.24 else
145 root 1.25 memset (ptr, 0, n);
146 root 1.23
147     return ptr;
148 root 1.3 }
149 root 1.11
150 root 1.69 /******************************************************************************/
151    
152 root 1.72 #if DEBUG_SALLOC
153 root 1.69
154 root 1.70 #define MAGIC 0xa1b2c35543deadLL
155 root 1.69
156 root 1.99 void *
157     g_slice_alloc (unsigned long size)
158 root 1.69 {
159     unsigned long *p = (unsigned long *) (g_slice_alloc)(size + sizeof (unsigned long));
160     *p++ = size ^ MAGIC;
161     //fprintf (stderr, "g_slice_alloc %ld %p\n", size, p);//D
162     return (void *)p;
163     }
164    
165 root 1.99 void *
166     g_slice_alloc0 (unsigned long size)
167 root 1.69 {
168     return memset (g_slice_alloc (size), 0, size);
169     }
170    
171 root 1.99 void
172     g_slice_free1 (unsigned long size, void *ptr)
173 root 1.69 {
174 root 1.74 //fprintf (stderr, "g_slice_free %ld %p\n", size, ptr);//D
175 root 1.109 if (ecb_expect_true (ptr))
176 root 1.69 {
177     unsigned long *p = (unsigned long *)ptr;
178     unsigned long s = *--p ^ MAGIC;
179    
180 root 1.71 if (size != (unsigned long)(*p ^ MAGIC))
181 root 1.74 {
182     LOG (logBacktrace | llevError, "slice free size (%lx) doesn't match alloc size (%lx)\n", size, s);
183     abort ();
184     }
185 root 1.69
186     *p = MAGIC;
187    
188     (g_slice_free1)(s + sizeof (unsigned long), p);
189     }
190     }
191    
192     #endif
193    
194     /******************************************************************************/
195    
196 root 1.99 refcnt_buf::refcnt_buf (size_t size)
197     {
198 root 1.102 static uint32_t empty_buf [2] = { 0, 1 }; // 2 == never deallocated
199     data = (char *)empty_buf + overhead;
200     assert (overhead == sizeof (empty_buf));
201     inc ();
202 root 1.99 }
203    
204     refcnt_buf::refcnt_buf (void *data, size_t size)
205     {
206     _alloc (size);
207     memcpy (this->data, data, size);
208     }
209    
210     refcnt_buf::~refcnt_buf ()
211     {
212     dec ();
213     }
214    
215 root 1.102 void
216     refcnt_buf::_dealloc ()
217     {
218     sfree<char> (data - overhead, size () + overhead);
219     }
220    
221 root 1.99 refcnt_buf &
222     refcnt_buf::operator =(const refcnt_buf &src)
223     {
224     dec ();
225     data = src.data;
226 root 1.102 inc ();
227 root 1.99 return *this;
228     }
229    
230     /******************************************************************************/
231    
232 root 1.86 int
233     assign (char *dst, const char *src, int maxsize)
234 root 1.11 {
235     if (!src)
236     src = "";
237    
238     int len = strlen (src);
239    
240 root 1.86 if (len >= maxsize)
241 root 1.11 {
242 root 1.86 if (maxsize <= 4)
243 root 1.11 {
244 root 1.86 memset (dst, '.', maxsize - 2);
245     dst [maxsize - 1] = 0;
246 root 1.11 }
247     else
248     {
249 root 1.86 memcpy (dst, src, maxsize - 4);
250     memcpy (dst + maxsize - 4, "...", 4);
251 root 1.11 }
252 root 1.86
253     len = maxsize;
254 root 1.11 }
255     else
256 root 1.86 memcpy (dst, src, ++len);
257    
258     return len;
259 root 1.11 }
260    
261 root 1.90 char *
262     vformat (const char *format, va_list ap)
263     {
264 root 1.96 static dynbuf_text bufs[8];
265     static int bufidx;
266    
267     dynbuf_text &buf = bufs [++bufidx & 7];
268    
269     buf.clear ();
270 root 1.90 buf.vprintf (format, ap);
271     return buf;
272     }
273    
274     char *
275 root 1.51 format (const char *format, ...)
276     {
277 root 1.65 va_list ap;
278     va_start (ap, format);
279 root 1.90 char *buf = vformat (format, ap);
280 root 1.65 va_end (ap);
281    
282     return buf;
283 root 1.51 }
284    
285 root 1.99 tstamp
286     now ()
287 root 1.23 {
288     struct timeval tv;
289    
290     gettimeofday (&tv, 0);
291     return tstamp (tv.tv_sec) + tstamp (tv.tv_usec) * tstamp (1e-6);
292     }
293 root 1.17
294 root 1.32 int
295     similar_direction (int a, int b)
296     {
297     if (!a || !b)
298     return 0;
299    
300     int diff = (b - a) & 7;
301     return diff <= 1 || diff >= 7;
302     }
303    
304 root 1.48 /* crc32 0xdebb20e3 table and supplementary functions. */
305     extern const uint32_t crc_32_tab[256] =
306     {
307     0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
308     0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
309     0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
310     0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
311     0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
312     0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
313     0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
314     0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
315     0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
316     0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
317     0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
318     0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
319     0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
320     0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
321     0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
322     0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
323     0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
324     0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
325     0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
326     0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
327     0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
328     0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
329     0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
330     0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
331     0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
332     0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
333     0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
334     0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
335     0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
336     0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
337     0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
338     0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
339     0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
340     0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
341     0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
342     0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
343     0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
344     0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
345     0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
346     0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
347     0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
348     0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
349     0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
350     0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
351     0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
352     0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
353     0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
354     0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
355     0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
356     0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
357     0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
358     0x2d02ef8dL
359     };
360    
361 root 1.99 void
362     thread::start (void *(*start_routine)(void *), void *arg)
363 root 1.73 {
364 root 1.75 pthread_attr_t attr;
365    
366     pthread_attr_init (&attr);
367     pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
368     pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < sizeof (long) * 4096
369     ? sizeof (long) * 4096 : PTHREAD_STACK_MIN);
370     #ifdef PTHREAD_SCOPE_PROCESS
371     pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS);
372     #endif
373    
374 root 1.73 sigset_t fullsigset, oldsigset;
375     sigfillset (&fullsigset);
376    
377     pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset);
378    
379 root 1.75 if (pthread_create (&id, &attr, start_routine, arg))
380 root 1.73 cleanup ("unable to create a new thread");
381    
382     pthread_sigmask (SIG_SETMASK, &oldsigset, 0);
383     }
384 root 1.75