1 // -*- C++ -*- 2 3 // Utility subroutines for the C++ library testsuite. 4 // 5 // Copyright (C) 2002-2020 Free Software Foundation, Inc. 6 // 7 // This file is part of the GNU ISO C++ Library. This library is free 8 // software; you can redistribute it and/or modify it under the 9 // terms of the GNU General Public License as published by the 10 // Free Software Foundation; either version 3, or (at your option) 11 // any later version. 12 // 13 // This library is distributed in the hope that it will be useful, 14 // but WITHOUT ANY WARRANTY; without even the implied warranty of 15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 // GNU General Public License for more details. 17 // 18 // You should have received a copy of the GNU General Public License along 19 // with this library; see the file COPYING3. If not see 20 // <http://www.gnu.org/licenses/>. 21 // 22 23 #include <testsuite_hooks.h> 24 25 #ifdef _GLIBCXX_RES_LIMITS 26 #include <unistd.h> 27 #include <sys/time.h> 28 #include <sys/resource.h> 29 #endif 30 31 #include <list> 32 #include <string> 33 #include <stdexcept> 34 #include <clocale> 35 #include <cstdlib> 36 #include <locale> 37 #include <cxxabi.h> 38 39 // If we have <sys/types.h>, <sys/ipc.h>, and <sys/sem.h>, then assume 40 // that System V semaphores are available. 41 #if defined(_GLIBCXX_HAVE_SYS_TYPES_H) \ 42 && defined(_GLIBCXX_HAVE_SYS_IPC_H) \ 43 && defined(_GLIBCXX_HAVE_SYS_SEM_H) 44 #define _GLIBCXX_SYSV_SEM 45 #endif 46 47 #ifdef _GLIBCXX_SYSV_SEM 48 #include <sys/types.h> 49 #include <sys/ipc.h> 50 #include <sys/sem.h> 51 #endif 52 53 namespace __gnu_test 54 { 55 #ifdef _GLIBCXX_RES_LIMITS 56 void set_memory_limits(float size)57 set_memory_limits(float size) 58 { 59 struct rlimit r; 60 // Cater to the absence of rlim_t. 61 __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur))(size * 1048576); 62 63 // Heap size, seems to be common. 64 #if _GLIBCXX_HAVE_LIMIT_DATA 65 getrlimit(RLIMIT_DATA, &r); 66 r.rlim_cur = limit; 67 setrlimit(RLIMIT_DATA, &r); 68 #endif 69 70 // Resident set size. 71 #if _GLIBCXX_HAVE_LIMIT_RSS 72 getrlimit(RLIMIT_RSS, &r); 73 r.rlim_cur = limit; 74 setrlimit(RLIMIT_RSS, &r); 75 #endif 76 77 // Mapped memory (brk + mmap). 78 #if _GLIBCXX_HAVE_LIMIT_VMEM 79 getrlimit(RLIMIT_VMEM, &r); 80 r.rlim_cur = limit; 81 setrlimit(RLIMIT_VMEM, &r); 82 #endif 83 84 // Virtual memory. On x86_64-linux, the default is -z 85 // max-page-size=0x200000 which means up to 2MB of address space 86 // are accounted for PROT_NONE mappings between text and data 87 // segments of each shared library. There are 4 shared libs 88 // involved in addition to the dynamic linker, maybe 5 if libgomp 89 // is being used as well. Use at least 20MB address space limit. 90 #if defined(__x86_64__) && defined(__linux__) 91 if (limit < 20971520) 92 limit = 20971520; 93 #endif 94 95 // On HP-UX 11.23, a trivial C++ program that sets RLIMIT_AS to 96 // anything less than 128MB cannot "malloc" even 1K of memory. 97 // Therefore, we skip RLIMIT_AS on HP-UX. 98 #if _GLIBCXX_HAVE_LIMIT_AS && !defined(__hpux__) 99 getrlimit(RLIMIT_AS, &r); 100 r.rlim_cur = limit; 101 setrlimit(RLIMIT_AS, &r); 102 #endif 103 } 104 105 #else 106 void 107 set_memory_limits(float) { } 108 #endif 109 110 #ifdef _GLIBCXX_RES_LIMITS 111 void set_file_limit(unsigned long size)112 set_file_limit(unsigned long size) 113 { 114 #if _GLIBCXX_HAVE_LIMIT_FSIZE 115 struct rlimit r; 116 // Cater to the absence of rlim_t. 117 __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur))(size); 118 119 getrlimit(RLIMIT_FSIZE, &r); 120 r.rlim_cur = limit; 121 setrlimit(RLIMIT_FSIZE, &r); 122 #endif 123 } 124 125 #else 126 void set_file_limit(unsigned long)127 set_file_limit(unsigned long) { } 128 #endif 129 130 void verify_demangle(const char * mangled,const char * wanted)131 verify_demangle(const char* mangled, const char* wanted) 132 { 133 int status = 0; 134 const char* s = 0; 135 char* demangled = abi::__cxa_demangle(mangled, 0, 0, &status); 136 if (demangled) 137 s = demangled; 138 else 139 { 140 switch (status) 141 { 142 case 0: 143 s = "error code = 0: success"; 144 break; 145 case -1: 146 s = "error code = -1: memory allocation failure"; 147 break; 148 case -2: 149 s = "error code = -2: invalid mangled name"; 150 break; 151 case -3: 152 s = "error code = -3: invalid arguments"; 153 break; 154 default: 155 s = "error code unknown - who knows what happened"; 156 } 157 } 158 159 std::string w(wanted); 160 if (w != s) 161 std::__throw_runtime_error(s); 162 free(demangled); 163 } 164 165 void run_tests_wrapped_locale(const char * name,const func_callback & l)166 run_tests_wrapped_locale(const char* name, const func_callback& l) 167 { 168 using namespace std; 169 170 // Set the global locale. 171 locale loc_name = locale(name); 172 locale orig = locale::global(loc_name); 173 174 const char* res = setlocale(LC_ALL, name); 175 if (res) 176 { 177 string preLC_ALL = res; 178 const func_callback::test_type* tests = l.tests(); 179 for (int i = 0; i < l.size(); ++i) 180 (*tests[i])(); 181 string postLC_ALL= setlocale(LC_ALL, 0); 182 VERIFY( preLC_ALL == postLC_ALL ); 183 } 184 else 185 { 186 string s("LC_ALL for "); 187 s += name; 188 __throw_runtime_error(s.c_str()); 189 } 190 } 191 192 void run_tests_wrapped_env(const char * name,const char * env,const func_callback & l)193 run_tests_wrapped_env(const char* name, const char* env, 194 const func_callback& l) 195 { 196 using namespace std; 197 198 #ifdef _GLIBCXX_HAVE_SETENV 199 // Set the global locale. 200 locale loc_name = locale(name); 201 locale orig = locale::global(loc_name); 202 203 // Set environment variable env to value in name. 204 const char* oldENV = getenv(env); 205 if (!setenv(env, name, 1)) 206 { 207 const func_callback::test_type* tests = l.tests(); 208 for (int i = 0; i < l.size(); ++i) 209 (*tests[i])(); 210 setenv(env, oldENV ? oldENV : "", 1); 211 } 212 else 213 { 214 string s(env); 215 s += string(" to "); 216 s += string(name); 217 __throw_runtime_error(s.c_str()); 218 } 219 #endif 220 } 221 222 object_counter::size_type object_counter::count = 0; 223 unsigned int copy_constructor::count_ = 0; 224 unsigned int copy_constructor::throw_on_ = 0; 225 unsigned int assignment_operator::count_ = 0; 226 unsigned int assignment_operator::throw_on_ = 0; 227 unsigned int destructor::_M_count = 0; 228 int copy_tracker::next_id_ = 0; 229 230 #ifdef _GLIBCXX_SYSV_SEM 231 // This union is not declared in system headers. Instead, it must 232 // be defined by user programs. 233 union semun 234 { 235 int val; 236 struct semid_ds *buf; 237 unsigned short *array; 238 }; 239 #endif 240 semaphore()241 semaphore::semaphore() 242 { 243 #ifdef _GLIBCXX_SYSV_SEM 244 // Remember the PID for the process that created the semaphore set 245 // so that only one process will destroy the set. 246 pid_ = getpid(); 247 248 // GLIBC does not define SEM_R and SEM_A. 249 #ifndef SEM_R 250 #define SEM_R 0400 251 #endif 252 253 #ifndef SEM_A 254 #define SEM_A 0200 255 #endif 256 257 // Get a semaphore set with one semaphore. 258 sem_set_ = semget(IPC_PRIVATE, 1, SEM_R | SEM_A); 259 if (sem_set_ == -1) 260 std::__throw_runtime_error("could not obtain semaphore set"); 261 262 // Initialize the semaphore. 263 union semun val; 264 val.val = 0; 265 if (semctl(sem_set_, 0, SETVAL, val) == -1) 266 std::__throw_runtime_error("could not initialize semaphore"); 267 #else 268 // There are no semaphores on this system. We have no way to mark 269 // a test as "unsupported" at runtime, so we just exit, pretending 270 // that the test passed. 271 exit(0); 272 #endif 273 } 274 ~semaphore()275 semaphore::~semaphore() 276 { 277 #ifdef _GLIBCXX_SYSV_SEM 278 union semun val; 279 val.val = 0; // Avoid uninitialized variable warning. 280 // Destroy the semaphore set only in the process that created it. 281 if (pid_ == getpid()) 282 semctl(sem_set_, 0, IPC_RMID, val); 283 #endif 284 } 285 286 void signal()287 semaphore::signal() 288 { 289 #ifdef _GLIBCXX_SYSV_SEM 290 struct sembuf op[1] = 291 { 292 { 0, 1, 0 } 293 }; 294 if (semop(sem_set_, op, 1) == -1) 295 std::__throw_runtime_error("could not signal semaphore"); 296 #endif 297 } 298 299 void wait()300 semaphore::wait() 301 { 302 #ifdef _GLIBCXX_SYSV_SEM 303 struct sembuf op[1] = 304 { 305 { 0, -1, SEM_UNDO } 306 }; 307 if (semop(sem_set_, op, 1) == -1) 308 std::__throw_runtime_error("could not wait for semaphore"); 309 #endif 310 } 311 312 // For use in 22_locale/time_get and time_put. 313 std::tm test_tm(int sec,int min,int hour,int mday,int mon,int year,int wday,int yday,int isdst)314 test_tm(int sec, int min, int hour, int mday, int mon, 315 int year, int wday, int yday, int isdst) 316 { 317 static std::tm tmp; 318 tmp.tm_sec = sec; 319 tmp.tm_min = min; 320 tmp.tm_hour = hour; 321 tmp.tm_mday = mday; 322 tmp.tm_mon = mon; 323 tmp.tm_year = year; 324 tmp.tm_wday = wday; 325 tmp.tm_yday = yday; 326 tmp.tm_isdst = isdst; 327 return tmp; 328 } 329 } // namespace __gnu_test 330