Mercurial > ~astiob > upreckon > hgweb
comparison _unixmodule.cpp @ 136:ed4035661b85
Added a C implementation of the unix module (called _unix)
| author | Oleg Oshmyan <chortos@inbox.lv> |
|---|---|
| date | Tue, 24 May 2011 20:51:01 +0100 |
| parents | |
| children | f4361d557929 |
comparison
equal
deleted
inserted
replaced
| 135:523ba6907f3a | 136:ed4035661b85 |
|---|---|
| 1 // Copyright (c) 2011 Chortos-2 <chortos@inbox.lv> | |
| 2 | |
| 3 #include <Python.h> | |
| 4 #include <structmember.h> | |
| 5 | |
| 6 #ifdef HAVE_SYS_TYPES_H | |
| 7 #include <sys/types.h> | |
| 8 #endif | |
| 9 | |
| 10 #ifdef HAVE_FCNTL_H | |
| 11 #include <fcntl.h> | |
| 12 #endif | |
| 13 | |
| 14 #include <limits.h> | |
| 15 | |
| 16 #ifdef HAVE_SIGNAL_H | |
| 17 #include <signal.h> | |
| 18 #endif | |
| 19 | |
| 20 #ifdef HAVE_SPAWN_H | |
| 21 #include <spawn.h> | |
| 22 #ifdef __APPLE__ | |
| 23 #pragma weak_import posix_spawnp | |
| 24 #endif | |
| 25 #endif | |
| 26 | |
| 27 #ifdef HAVE_SYS_RESOURCE_H | |
| 28 #include <sys/resource.h> | |
| 29 #endif | |
| 30 | |
| 31 #ifdef HAVE_SYS_WAIT_H | |
| 32 #include <sys/wait.h> | |
| 33 #endif | |
| 34 | |
| 35 #ifdef HAVE_TERMIOS_H | |
| 36 #include <termios.h> | |
| 37 #endif | |
| 38 | |
| 39 #if !(defined __cplusplus) && !(defined bool) | |
| 40 #ifdef HAVE_C99_BOOL | |
| 41 #define bool _Bool | |
| 42 #else | |
| 43 #define bool char | |
| 44 #endif | |
| 45 #undef true | |
| 46 #define true 1 | |
| 47 #undef false | |
| 48 #define false 0 | |
| 49 #endif | |
| 50 | |
| 51 // On Python 2.5, SIGINT handling may get delayed until we return to Python | |
| 52 #if PY_MAJOR_VERSION > 2 || PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 6 | |
| 53 #define USE_WAKEUP_FD | |
| 54 #endif | |
| 55 | |
| 56 #if !(defined RLIMIT_AS) && defined RLIMIT_VMEM | |
| 57 #define RLIMIT_AS RLIMIT_VMEM | |
| 58 #endif | |
| 59 | |
| 60 // Condition stolen from posixmodule.c of Python 2.7.1 | |
| 61 #if defined __USLC__ && defined __SCO_VERSION__ // SCO UDK Compiler | |
| 62 //#ifdef HAVE_FORK1 | |
| 63 #define fork fork1 | |
| 64 #endif | |
| 65 | |
| 66 // Stolen from posixmodule.c of Python 2.7.1 | |
| 67 #ifdef WITH_NEXT_FRAMEWORK | |
| 68 #include <crt_externs.h> | |
| 69 static char **environ = NULL; | |
| 70 #elif !(defined _MSC_VER) && (!(defined __WATCOMC__) || defined __QNX__) | |
| 71 extern char **environ; | |
| 72 #endif | |
| 73 | |
| 74 #ifndef Py_PYTIME_H | |
| 75 typedef struct timeval _PyTime_timeval; | |
| 76 #ifndef GETTIMEOFDAY_NO_TZ | |
| 77 #define _PyTime_gettimeofday(tvp) gettimeofday((tvp), NULL) | |
| 78 #else | |
| 79 #define _PyTime_gettimeofday(tvp) gettimeofday((tvp)) | |
| 80 #endif | |
| 81 #endif | |
| 82 | |
| 83 #if PY_MAJOR_VERSION >= 3 | |
| 84 #define PyInt_AsLong PyLong_AsLong | |
| 85 #define PyInt_FromLong PyLong_FromLong | |
| 86 #define PyNumber_Int PyNumber_Long | |
| 87 #endif | |
| 88 | |
| 89 #define TESTEE_SPAWNED 0 | |
| 90 #define TESTEE_SPAWN_FAILED 1 | |
| 91 #define TESTEE_REPORT_STATUS(status) \ | |
| 92 do \ | |
| 93 { \ | |
| 94 const char c = (status); \ | |
| 95 write(c2ppipe[1], &c, 1); \ | |
| 96 } \ | |
| 97 while (0) | |
| 98 | |
| 99 #if !(defined SIGKILL) && defined SIGTERM | |
| 100 #define SIGKILL SIGTERM | |
| 101 #endif | |
| 102 | |
| 103 #if defined HAVE_KILL && defined SIGKILL | |
| 104 #ifdef HAVE_WAITPID | |
| 105 #define TERM_TESTEE \ | |
| 106 do \ | |
| 107 { \ | |
| 108 kill(-curpid, SIGKILL); \ | |
| 109 kill(-curpid, SIGCONT); \ | |
| 110 while (waitpid(curpid, &retstat, 0) != curpid); \ | |
| 111 } \ | |
| 112 while (0) | |
| 113 #else | |
| 114 #define TERM_TESTEE \ | |
| 115 do \ | |
| 116 { \ | |
| 117 kill(-curpid, SIGKILL); \ | |
| 118 kill(-curpid, SIGCONT); \ | |
| 119 while (wait(&retstat) != curpid); \ | |
| 120 } \ | |
| 121 while (0) | |
| 122 #endif | |
| 123 #else | |
| 124 #define TERM_TESTEE | |
| 125 #endif | |
| 126 | |
| 127 #if defined HAVE_KILL && defined SIGINT | |
| 128 #define PROPAGATE_SIGINT ((void) kill(-curpid, SIGINT)) | |
| 129 #else | |
| 130 #define PROPAGATE_SIGINT | |
| 131 #endif | |
| 132 | |
| 133 struct child_stats | |
| 134 { | |
| 135 int returncode; | |
| 136 _PyTime_timeval walltime; | |
| 137 #if defined HAVE_SYS_RESOURCE_H || defined HAVE_WAIT4 || defined HAVE_WAIT3 | |
| 138 _PyTime_timeval cputime; | |
| 139 Py_ssize_t memory; | |
| 140 #endif | |
| 141 }; | |
| 142 | |
| 143 static pid_t curpid; | |
| 144 static const struct child_stats zero_stats = { 0 }; | |
| 145 static PyObject *CannotStartTestee, *CanceledByUser, *WallTimeLimitExceeded, | |
| 146 *CPUTimeLimitExceeded, *MemoryLimitExceeded; | |
| 147 static _PyTime_timeval time_end; | |
| 148 | |
| 149 #ifdef USE_WAKEUP_FD | |
| 150 static char dont_care_buffer[512]; | |
| 151 static int intpipe[2] = { 0 }; | |
| 152 #endif | |
| 153 | |
| 154 #ifdef HAVE_TERMIOS_H | |
| 155 static bool catch_escape = false; | |
| 156 static struct termios orig_termios; | |
| 157 #endif | |
| 158 | |
| 159 typedef struct | |
| 160 { | |
| 161 PyObject_HEAD | |
| 162 int returncode; | |
| 163 } _unix__PopenPlaceholderObject; | |
| 164 | |
| 165 static PyMemberDef _PopenPlaceholder_members[] = | |
| 166 { | |
| 167 { "returncode", T_INT, offsetof(_unix__PopenPlaceholderObject, returncode), READONLY, NULL }, | |
| 168 { NULL } | |
| 169 }; | |
| 170 | |
| 171 static PyTypeObject _unix__PopenPlaceholderType = | |
| 172 { | |
| 173 #if PY_MAJOR_VERSION >= 3 | |
| 174 PyVarObject_HEAD_INIT(NULL, 0) | |
| 175 #else | |
| 176 PyObject_HEAD_INIT(NULL) | |
| 177 0, /*ob_size*/ | |
| 178 #endif | |
| 179 "_unix._PopenPlaceholder", /*tp_name*/ | |
| 180 sizeof(_unix__PopenPlaceholderObject), /*tp_basicsize*/ | |
| 181 0, /*tp_itemsize*/ | |
| 182 0, /*tp_dealloc*/ | |
| 183 0, /*tp_print*/ | |
| 184 0, /*tp_getattr*/ | |
| 185 0, /*tp_setattr*/ | |
| 186 0, /*tp_compare*/ | |
| 187 0, /*tp_repr*/ | |
| 188 0, /*tp_as_number*/ | |
| 189 0, /*tp_as_sequence*/ | |
| 190 0, /*tp_as_mapping*/ | |
| 191 0, /*tp_hash */ | |
| 192 0, /*tp_call*/ | |
| 193 0, /*tp_str*/ | |
| 194 0, /*tp_getattro*/ | |
| 195 0, /*tp_setattro*/ | |
| 196 0, /*tp_as_buffer*/ | |
| 197 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ | |
| 198 0, /*tp_doc*/ | |
| 199 0, /*tp_traverse*/ | |
| 200 0, /*tp_clear*/ | |
| 201 0, /*tp_richcompare*/ | |
| 202 0, /*tp_weaklistoffset*/ | |
| 203 0, /*tp_iter*/ | |
| 204 0, /*tp_iternext*/ | |
| 205 0, /*tp_methods*/ | |
| 206 _PopenPlaceholder_members, /*tp_members*/ | |
| 207 }; | |
| 208 | |
| 209 #ifndef timeradd | |
| 210 #define timeradd(a, b, res) \ | |
| 211 do \ | |
| 212 { \ | |
| 213 (res)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ | |
| 214 (res)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ | |
| 215 if ((res)->tv_usec >= 1000000) \ | |
| 216 { \ | |
| 217 ++(res)->tv_sec; \ | |
| 218 (res)->tv_usec -= 1000000; \ | |
| 219 } \ | |
| 220 } \ | |
| 221 while (0) | |
| 222 #endif | |
| 223 | |
| 224 #ifndef timersub | |
| 225 #define timersub(a, b, res) \ | |
| 226 do \ | |
| 227 { \ | |
| 228 (res)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ | |
| 229 (res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ | |
| 230 if ((res)->tv_usec < 0) \ | |
| 231 { \ | |
| 232 --(res)->tv_sec; \ | |
| 233 (res)->tv_usec += 1000000; \ | |
| 234 } \ | |
| 235 } \ | |
| 236 while (0) | |
| 237 #endif | |
| 238 | |
| 239 #ifndef timerclear | |
| 240 #define timerclear(tvp) ((void) ((tvp)->tv_sec = (tvp)->tv_usec = 0)) | |
| 241 #endif | |
| 242 | |
| 243 #ifndef timerisset | |
| 244 #define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) | |
| 245 #endif | |
| 246 | |
| 247 #ifndef timercmp | |
| 248 #define timercmp(a, b, cmp) \ | |
| 249 (((a)->tv_sec == (b)->tv_sec) \ | |
| 250 ? ((a)->tv_usec cmp (b)->tv_usec) \ | |
| 251 : ((a)->tv_sec cmp (b)->tv_sec)) | |
| 252 #endif | |
| 253 | |
| 254 // Stolen from posixmodule.c of Python 2.7.1 | |
| 255 static void free_string_array(char **array, Py_ssize_t count) | |
| 256 { | |
| 257 Py_ssize_t i; | |
| 258 for (i = 0; i < count; ++i) | |
| 259 PyMem_Free(array[i]); | |
| 260 PyMem_DEL(array); | |
| 261 } | |
| 262 | |
| 263 // Stolen from termios.c of Python 2.7.1 | |
| 264 static int fdconv(PyObject *obj, void *p) | |
| 265 { | |
| 266 int fd = PyObject_AsFileDescriptor(obj); | |
| 267 if (fd >= 0) | |
| 268 { | |
| 269 *((int *) p) = fd; | |
| 270 return 1; | |
| 271 } | |
| 272 return 0; | |
| 273 } | |
| 274 | |
| 275 // Parts stolen from bltinmodule.c, posixmodule.c and termios.c of Python 2.7.1 | |
| 276 static int my_spawn(PyObject *args, PyObject *kwds, int c2ppipe[2], int maxcputime, Py_ssize_t maxmemory) | |
| 277 { | |
| 278 static const char *const kwlist[] = { "stdin", "stdout", "stderr", NULL }; | |
| 279 static PyObject *dummy_args = NULL; | |
| 280 Py_ssize_t i, argc; | |
| 281 char **argv; | |
| 282 bool own_args = false; | |
| 283 int fdin = 0, fdout = 1, fderr = 2; | |
| 284 | |
| 285 if (dummy_args == NULL) | |
| 286 { | |
| 287 if (!(dummy_args = PyTuple_New(0))) | |
| 288 { | |
| 289 return -1; | |
| 290 } | |
| 291 } | |
| 292 | |
| 293 if (!PyArg_ParseTuple(args, "O:call", &args)) | |
| 294 { | |
| 295 return -1; | |
| 296 } | |
| 297 if (!PyArg_ParseTupleAndKeywords(dummy_args, kwds, "|O&O&O&:call", (char **) kwlist, fdconv, &fdin, fdconv, &fdout, fdconv, &fderr)) | |
| 298 { | |
| 299 return -1; | |
| 300 } | |
| 301 | |
| 302 #if PY_MAJOR_VERSION >= 3 | |
| 303 if (PyUnicode_Check(args)) | |
| 304 #else | |
| 305 if (PyString_Check(args) || PyUnicode_Check(args)) | |
| 306 #endif | |
| 307 { | |
| 308 argc = 1; | |
| 309 args = PyTuple_Pack(1, args); | |
| 310 if (args == NULL) | |
| 311 { | |
| 312 return -1; | |
| 313 } | |
| 314 own_args = true; | |
| 315 } | |
| 316 else if (!PySequence_Check(args)) | |
| 317 { | |
| 318 PyErr_SetString(PyExc_TypeError, "call() argument must be a sequence or string"); | |
| 319 return -1; | |
| 320 } | |
| 321 else | |
| 322 { | |
| 323 argc = PySequence_Size(args); | |
| 324 if (argc < 1) | |
| 325 { | |
| 326 PyErr_SetString(PyExc_TypeError, "call() argument must not be empty"); | |
| 327 return -1; | |
| 328 } | |
| 329 } | |
| 330 | |
| 331 argv = PyMem_NEW(char *, argc + 1); | |
| 332 if (argv == NULL) | |
| 333 { | |
| 334 if (own_args) | |
| 335 { | |
| 336 Py_DECREF(args); | |
| 337 } | |
| 338 PyErr_NoMemory(); | |
| 339 return -1; | |
| 340 } | |
| 341 | |
| 342 for (i = 0; i < argc; ++i) | |
| 343 { | |
| 344 if (!PyArg_Parse(PySequence_ITEM(args, i), "et", Py_FileSystemDefaultEncoding, &argv[i])) | |
| 345 { | |
| 346 free_string_array(argv, i); | |
| 347 if (own_args) | |
| 348 { | |
| 349 Py_DECREF(args); | |
| 350 } | |
| 351 PyErr_SetString(PyExc_TypeError, "call() argument must contain only strings"); | |
| 352 return -1; | |
| 353 } | |
| 354 } | |
| 355 argv[argc] = NULL; | |
| 356 | |
| 357 curpid = fork(); | |
| 358 if (!curpid) | |
| 359 { | |
| 360 pid_t pid; | |
| 361 int spawn_errno, status, fd, fddupped[3]; | |
| 362 struct child_stats stats; | |
| 363 _PyTime_timeval tvstart, tvend; | |
| 364 #if defined HAVE_SYS_RESOURCE_H || defined HAVE_WAIT4 || defined HAVE_WAIT3 | |
| 365 struct rusage rusage; | |
| 366 #endif | |
| 367 #if defined RLIMIT_AS || defined RLIMIT_CPU | |
| 368 struct rlimit rlimit; | |
| 369 #endif | |
| 370 | |
| 371 /* | |
| 372 Assume no errors occur: | |
| 373 * POSIX:2008 doesn't even define any errors for setpgrp, | |
| 374 nor does the (probably copied-verbatim-from-FreeBSD) man page | |
| 375 on Mac OS X 10.6; | |
| 376 * none of the error conditions POSIX:2008 does define | |
| 377 for setpgid can occur. | |
| 378 */ | |
| 379 #ifdef HAVE_SETPGID | |
| 380 setpgid(0, 0); | |
| 381 #else //if defined HAVE_SETPGRP | |
| 382 #ifdef SETPGRP_HAVE_ARG | |
| 383 setpgrp(0, 0); | |
| 384 #else | |
| 385 setpgrp(); | |
| 386 #endif | |
| 387 #endif | |
| 388 | |
| 389 #ifdef SIGINT | |
| 390 signal(SIGINT, SIG_DFL); | |
| 391 #endif | |
| 392 | |
| 393 #if PY_MAJOR_VERSION > 3 || PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 2 | |
| 394 _Py_RestoreSignals(); | |
| 395 #else | |
| 396 #ifdef SIGPIPE | |
| 397 signal(SIGPIPE, SIG_DFL); | |
| 398 #endif | |
| 399 #ifdef SIGXFSZ | |
| 400 signal(SIGXFSZ, SIG_DFL); | |
| 401 #endif | |
| 402 #ifdef SIGXFZ | |
| 403 signal(SIGXFZ, SIG_DFL); | |
| 404 #endif | |
| 405 #endif | |
| 406 | |
| 407 if (c2ppipe[1] < 3) | |
| 408 { | |
| 409 int newfd; | |
| 410 #ifdef F_DUPFD_CLOEXEC | |
| 411 newfd = fcntl(c2ppipe[1], F_DUPFD_CLOEXEC, 3); | |
| 412 if (newfd == -1) | |
| 413 { | |
| 414 spawn_errno = errno; | |
| 415 TESTEE_REPORT_STATUS(TESTEE_SPAWN_FAILED); | |
| 416 write(c2ppipe[1], &spawn_errno, sizeof spawn_errno); | |
| 417 _exit(127); | |
| 418 } | |
| 419 c2ppipe[1] = newfd; | |
| 420 #else | |
| 421 newfd = fcntl(c2ppipe[1], F_DUPFD, 3); | |
| 422 // Other threads should not fork/spawn right now | |
| 423 if (newfd == -1 | |
| 424 || fcntl(newfd, F_SETFD, fcntl(newfd, F_GETFD) | FD_CLOEXEC) == -1) | |
| 425 { | |
| 426 spawn_errno = errno; | |
| 427 TESTEE_REPORT_STATUS(TESTEE_SPAWN_FAILED); | |
| 428 write(c2ppipe[1], &spawn_errno, sizeof spawn_errno); | |
| 429 _exit(127); | |
| 430 } | |
| 431 c2ppipe[1] = newfd; | |
| 432 #endif | |
| 433 } | |
| 434 // Yes, this works as intended even if fdin == fdout == fderr == 0 | |
| 435 // and there are no open file descriptors except 0 and c2ppipe | |
| 436 // FIXME: error handling | |
| 437 fddupped[0] = dup(fdin); | |
| 438 fddupped[1] = dup(fdout); | |
| 439 fddupped[2] = dup(fderr); | |
| 440 dup2(fddupped[0], 0); | |
| 441 dup2(fddupped[1], 1); | |
| 442 dup2(fddupped[2], 2); | |
| 443 // FIXME: close() may fail with EINTR or EIO; is setting CLOEXEC safer? | |
| 444 // Bear in mind we still want to close them in _this_ process | |
| 445 for (fd = sysconf(_SC_OPEN_MAX); --fd > c2ppipe[1]; ) | |
| 446 { | |
| 447 close(fd); | |
| 448 } | |
| 449 while (--fd >= 3) | |
| 450 { | |
| 451 close(fd); | |
| 452 } | |
| 453 | |
| 454 #ifdef RLIMIT_AS | |
| 455 if (maxmemory) | |
| 456 { | |
| 457 rlimit.rlim_cur = rlimit.rlim_max = maxmemory; | |
| 458 setrlimit(RLIMIT_AS, &rlimit); | |
| 459 } | |
| 460 #endif | |
| 461 #ifdef RLIMIT_CPU | |
| 462 if (maxcputime) | |
| 463 { | |
| 464 rlimit.rlim_cur = rlimit.rlim_max = maxcputime; | |
| 465 setrlimit(RLIMIT_CPU, &rlimit); | |
| 466 } | |
| 467 #endif | |
| 468 | |
| 469 #ifdef HAVE_SPAWN_H | |
| 470 #ifdef __APPLE__ | |
| 471 if (posix_spawnp != NULL) | |
| 472 { | |
| 473 #endif | |
| 474 spawn_errno = posix_spawnp(&pid, argv[0], NULL, NULL, argv, environ); | |
| 475 _PyTime_gettimeofday(&tvstart); | |
| 476 | |
| 477 if (spawn_errno) | |
| 478 { | |
| 479 TESTEE_REPORT_STATUS(TESTEE_SPAWN_FAILED); | |
| 480 write(c2ppipe[1], &spawn_errno, sizeof spawn_errno); | |
| 481 _exit(127); | |
| 482 } | |
| 483 #ifdef __APPLE__ | |
| 484 } | |
| 485 else | |
| 486 #endif | |
| 487 #endif | |
| 488 #if !(defined HAVE_SPAWN_H) || defined __APPLE__ | |
| 489 { | |
| 490 pid = fork(); | |
| 491 if (!pid) | |
| 492 { | |
| 493 execvp(argv[0], argv); | |
| 494 spawn_errno = errno; | |
| 495 TESTEE_REPORT_STATUS(TESTEE_SPAWN_FAILED); | |
| 496 write(c2ppipe[1], &spawn_errno, sizeof spawn_errno); | |
| 497 _exit(127); | |
| 498 } | |
| 499 else if (pid == -1) | |
| 500 { | |
| 501 spawn_errno = errno; | |
| 502 TESTEE_REPORT_STATUS(TESTEE_SPAWN_FAILED); | |
| 503 write(c2ppipe[1], &spawn_errno, sizeof spawn_errno); | |
| 504 _exit(127); | |
| 505 } | |
| 506 else | |
| 507 { | |
| 508 _PyTime_gettimeofday(&tvstart); | |
| 509 } | |
| 510 } | |
| 511 #endif | |
| 512 TESTEE_REPORT_STATUS(TESTEE_SPAWNED); | |
| 513 write(c2ppipe[1], &tvstart, sizeof tvstart); | |
| 514 | |
| 515 #ifdef HAVE_WAIT4 | |
| 516 while (wait4(pid, &status, 0, &rusage) != pid); | |
| 517 #elif defined HAVE_WAIT3 | |
| 518 while (wait3(&status, 0, &rusage) != pid); | |
| 519 #elif defined HAVE_WAITPID | |
| 520 while (waitpid(pid, &status, 0) != pid); | |
| 521 #else | |
| 522 while (wait(&status) != pid); | |
| 523 #endif | |
| 524 | |
| 525 _PyTime_gettimeofday(&tvend); | |
| 526 #if defined HAVE_SYS_RESOURCE_H && !(defined HAVE_WAIT4 || defined HAVE_WAIT3) | |
| 527 getrusage(RUSAGE_CHILDREN, &rusage); | |
| 528 #endif | |
| 529 | |
| 530 stats = zero_stats; | |
| 531 | |
| 532 if (WIFEXITED(status) && WEXITSTATUS(status) == 127) _exit(127); | |
| 533 else if (WIFSIGNALED(status)) stats.returncode = -WTERMSIG(status); | |
| 534 else stats.returncode = WEXITSTATUS(status); | |
| 535 | |
| 536 timersub(&tvend, &tvstart, &stats.walltime); | |
| 537 #if defined HAVE_SYS_RESOURCE_H || defined HAVE_WAIT4 || defined HAVE_WAIT3 | |
| 538 timeradd(&rusage.ru_utime, &rusage.ru_stime, &stats.cputime); | |
| 539 #ifdef __APPLE__ | |
| 540 stats.memory = rusage.ru_maxrss; | |
| 541 #else | |
| 542 stats.memory = rusage.ru_maxrss << 10; | |
| 543 #endif | |
| 544 #endif | |
| 545 | |
| 546 write(c2ppipe[1], &stats, sizeof stats); | |
| 547 _exit(0); | |
| 548 } | |
| 549 else if (curpid == -1) | |
| 550 { | |
| 551 PyErr_SetFromErrno(PyExc_OSError); | |
| 552 free_string_array(argv, argc); | |
| 553 if (own_args) | |
| 554 { | |
| 555 Py_DECREF(args); | |
| 556 } | |
| 557 return 0; | |
| 558 } | |
| 559 | |
| 560 /* | |
| 561 Assume no errors occur if the child is still alive: | |
| 562 * the (probably copied-verbatim-from-FreeBSD) man page | |
| 563 on Mac OS X 10.6 doesn't even define any errors for setpgrp; | |
| 564 * none of the error conditions POSIX:2008 defines | |
| 565 for setpgid can occur. | |
| 566 */ | |
| 567 #ifdef HAVE_SETPGID | |
| 568 setpgid(curpid, 0); | |
| 569 #elif defined SETPGRP_HAVE_ARG | |
| 570 setpgrp(curpid, 0); | |
| 571 #endif | |
| 572 | |
| 573 free_string_array(argv, argc); | |
| 574 if (own_args) | |
| 575 { | |
| 576 Py_DECREF(args); | |
| 577 } | |
| 578 return 1; | |
| 579 } | |
| 580 | |
| 581 static inline bool attr_to_timeval(PyObject *obj, const char *attr, _PyTime_timeval *ptv) | |
| 582 { | |
| 583 #ifdef HAVE_LONG_LONG | |
| 584 long long i_whole; | |
| 585 #else | |
| 586 long i_whole; | |
| 587 #endif | |
| 588 PyObject *whole, *frac, *million, *usec, *usec_whole; | |
| 589 PyObject *member = PyObject_GetAttrString(obj, attr); | |
| 590 if (member == NULL) | |
| 591 { | |
| 592 return false; | |
| 593 } | |
| 594 if (member == Py_None) | |
| 595 { | |
| 596 Py_DECREF(member); | |
| 597 timerclear(ptv); | |
| 598 return true; | |
| 599 } | |
| 600 whole = PyNumber_Int(member); | |
| 601 if (whole == NULL) | |
| 602 { | |
| 603 Py_DECREF(member); | |
| 604 return false; | |
| 605 } | |
| 606 #ifdef HAVE_LONG_LONG | |
| 607 i_whole = PyLong_AsLongLong(whole); | |
| 608 #else | |
| 609 i_whole = PyInt_AsLong(whole); | |
| 610 #endif | |
| 611 if (i_whole == -1 && PyErr_Occurred() != NULL) | |
| 612 { | |
| 613 Py_DECREF(whole); | |
| 614 Py_DECREF(member); | |
| 615 return false; | |
| 616 } | |
| 617 // FIXME: detect time_t overflow | |
| 618 ptv->tv_sec = i_whole; | |
| 619 frac = PyNumber_Subtract(member, whole); | |
| 620 Py_DECREF(whole); | |
| 621 Py_DECREF(member); | |
| 622 if (frac == NULL) | |
| 623 { | |
| 624 return false; | |
| 625 } | |
| 626 million = PyInt_FromLong(1000000); | |
| 627 if (million == NULL) | |
| 628 { | |
| 629 Py_DECREF(frac); | |
| 630 return false; | |
| 631 } | |
| 632 usec = PyNumber_InPlaceMultiply(frac, million); | |
| 633 Py_DECREF(million); | |
| 634 Py_DECREF(frac); | |
| 635 if (usec == NULL) | |
| 636 { | |
| 637 return false; | |
| 638 } | |
| 639 usec_whole = PyNumber_Int(usec); | |
| 640 Py_DECREF(usec); | |
| 641 if (usec_whole == NULL) | |
| 642 { | |
| 643 return false; | |
| 644 } | |
| 645 // FIXME: a sanity check (0 <= value < 1000000) here wouldn't harm | |
| 646 ptv->tv_usec = PyInt_AsLong(usec_whole); | |
| 647 Py_DECREF(usec_whole); | |
| 648 return ptv->tv_usec != -1 || PyErr_Occurred() == NULL; | |
| 649 } | |
| 650 | |
| 651 #ifdef __cplusplus | |
| 652 typedef struct { char a[2]; } two_chars; | |
| 653 static char is_int(char); | |
| 654 static char is_int(signed char); | |
| 655 static char is_int(unsigned char); | |
| 656 static char is_int(short); | |
| 657 static char is_int(unsigned short); | |
| 658 static char is_int(int); | |
| 659 static char is_int(unsigned); | |
| 660 static char is_int(long); | |
| 661 static char is_int(unsigned long); | |
| 662 #ifdef HAVE_LONG_LONG | |
| 663 static char is_int(long long); | |
| 664 static char is_int(unsigned long long); | |
| 665 #endif | |
| 666 static two_chars is_int(...); | |
| 667 #endif | |
| 668 | |
| 669 static inline bool timeval_to_attr(_PyTime_timeval *ptv, PyObject *obj, const char *attr) | |
| 670 { | |
| 671 PyObject *value; | |
| 672 #ifdef __cplusplus | |
| 673 // If tv_sec has an integral type and !tv_usec, try to create a Python int | |
| 674 if (sizeof is_int(ptv->tv_sec) == sizeof(char) && !ptv->tv_usec) | |
| 675 { | |
| 676 if (ptv->tv_sec <= LONG_MAX) | |
| 677 { | |
| 678 value = PyInt_FromLong(ptv->tv_sec); | |
| 679 } | |
| 680 // FIXME: signed/unsigned comparisons ruin everything | |
| 681 #ifdef HAVE_LONG_LONG | |
| 682 else// if (ptv->tv_sec <= ULLONG_MAX) | |
| 683 { | |
| 684 value = PyLong_FromUnsignedLongLong(ptv->tv_sec); | |
| 685 } | |
| 686 #else | |
| 687 // else if (ptv->tv_sec <= ULONG_MAX) | |
| 688 // { | |
| 689 // value = PyLong_FromUnsignedLong(ptv->tv_sec); | |
| 690 // } | |
| 691 //#endif | |
| 692 else | |
| 693 { | |
| 694 value = PyFloat_FromDouble(ptv->tv_sec); | |
| 695 } | |
| 696 // | |
| 697 #endif | |
| 698 // | |
| 699 } | |
| 700 else | |
| 701 #endif | |
| 702 { | |
| 703 // TODO: use decimal.Decimal or fractions.Fraction | |
| 704 value = PyFloat_FromDouble(ptv->tv_sec + ptv->tv_usec * 0.000001); | |
| 705 } | |
| 706 if (value == NULL) | |
| 707 { | |
| 708 return false; | |
| 709 } | |
| 710 if (PyObject_SetAttrString(obj, attr, value) == -1) | |
| 711 { | |
| 712 return false; | |
| 713 } | |
| 714 Py_DECREF(value); | |
| 715 return true; | |
| 716 } | |
| 717 | |
| 718 /* | |
| 719 TODO/FIXME: | |
| 720 * Replace timeval->timespec and select->pselect if pselect is available | |
| 721 (preferably only if pselect is not a wrapper around select). | |
| 722 * File descriptors might be >= FD_SETSIZE? | |
| 723 */ | |
| 724 static PyObject *_unix_call(PyObject *self, PyObject *args, PyObject *kwds) | |
| 725 { | |
| 726 PyObject *testcase = NULL, *obj; | |
| 727 _unix__PopenPlaceholderObject *Popen_placeholder; | |
| 728 int spawn_errno = 0, spawn_status, s, c2ppipe[2], retstat; | |
| 729 struct child_stats stats = zero_stats; | |
| 730 _PyTime_timeval maxwalltime, maxcputime, timeout, time_start; | |
| 731 Py_ssize_t maxmemory, r; | |
| 732 size_t stats_read = 0; | |
| 733 fd_set readfds; | |
| 734 char c; | |
| 735 bool have_maxwalltime; | |
| 736 | |
| 737 if (kwds != NULL) | |
| 738 { | |
| 739 testcase = PyDict_GetItemString(kwds, "case"); | |
| 740 } | |
| 741 if (testcase == NULL) | |
| 742 { | |
| 743 PyErr_SetString(PyExc_TypeError, "call() requires a keyword argument 'case'"); | |
| 744 return NULL; | |
| 745 } | |
| 746 Py_INCREF(testcase); | |
| 747 PyDict_DelItemString(kwds, "case"); | |
| 748 | |
| 749 if (!attr_to_timeval(testcase, "maxwalltime", &maxwalltime) | |
| 750 || !attr_to_timeval(testcase, "maxcputime", &maxcputime)) | |
| 751 { | |
| 752 Py_DECREF(testcase); | |
| 753 return NULL; | |
| 754 } | |
| 755 | |
| 756 obj = PyObject_GetAttrString(testcase, "maxmemory"); | |
| 757 if (obj == NULL) | |
| 758 { | |
| 759 Py_DECREF(testcase); | |
| 760 return NULL; | |
| 761 } | |
| 762 if (PyObject_IsTrue(obj)) | |
| 763 { | |
| 764 PyObject *factor, *bytes; | |
| 765 factor = PyInt_FromLong(1024 * 1024); | |
| 766 if (factor == NULL) | |
| 767 { | |
| 768 Py_DECREF(testcase); | |
| 769 return NULL; | |
| 770 } | |
| 771 bytes = PyNumber_Multiply(obj, factor); | |
| 772 Py_DECREF(factor); | |
| 773 if (bytes == NULL) | |
| 774 { | |
| 775 Py_DECREF(testcase); | |
| 776 return NULL; | |
| 777 } | |
| 778 maxmemory = PyNumber_AsSsize_t(bytes, PyExc_OverflowError); | |
| 779 Py_DECREF(bytes); | |
| 780 if (maxmemory == -1 && PyErr_Occurred() != NULL) | |
| 781 { | |
| 782 Py_DECREF(testcase); | |
| 783 return NULL; | |
| 784 } | |
| 785 } | |
| 786 else | |
| 787 { | |
| 788 maxmemory = 0; | |
| 789 } | |
| 790 Py_DECREF(obj); | |
| 791 | |
| 792 #ifdef HAVE_PIPE2 | |
| 793 if (pipe2(c2ppipe, O_CLOEXEC)) | |
| 794 { | |
| 795 PyErr_SetFromErrno(PyExc_IOError); | |
| 796 Py_DECREF(testcase); | |
| 797 return NULL; | |
| 798 } | |
| 799 #else | |
| 800 if (pipe(c2ppipe)) | |
| 801 { | |
| 802 PyErr_SetFromErrno(PyExc_IOError); | |
| 803 Py_DECREF(testcase); | |
| 804 return NULL; | |
| 805 } | |
| 806 // Does any other thread fork/spawn right now? Please shoot it in the head | |
| 807 // (well, if this ends up causing trouble, anyway) | |
| 808 if (fcntl(c2ppipe[0], F_SETFD, fcntl(c2ppipe[0], F_GETFD) | FD_CLOEXEC) == -1 | |
| 809 || fcntl(c2ppipe[1], F_SETFD, fcntl(c2ppipe[1], F_GETFD) | FD_CLOEXEC) == -1) | |
| 810 { | |
| 811 PyErr_SetFromErrno(PyExc_IOError); | |
| 812 close(c2ppipe[0]); | |
| 813 close(c2ppipe[1]); | |
| 814 Py_DECREF(testcase); | |
| 815 return NULL; | |
| 816 } | |
| 817 #endif | |
| 818 | |
| 819 spawn_status = my_spawn(args, kwds, c2ppipe, maxcputime.tv_sec + (maxcputime.tv_usec > 0), maxmemory); | |
| 820 close(c2ppipe[1]); | |
| 821 if (!spawn_status) | |
| 822 { | |
| 823 PyObject *type, *value, *traceback, *e; | |
| 824 close(c2ppipe[0]); | |
| 825 Py_DECREF(testcase); | |
| 826 PyErr_Fetch(&type, &value, &traceback); | |
| 827 PyErr_NormalizeException(&type, &value, &traceback); | |
| 828 Py_XDECREF(traceback); | |
| 829 Py_DECREF(type); | |
| 830 e = PyObject_CallFunctionObjArgs(CannotStartTestee, value, NULL); | |
| 831 Py_DECREF(value); | |
| 832 PyErr_SetObject(CannotStartTestee, e); | |
| 833 Py_DECREF(e); | |
| 834 return NULL; | |
| 835 } | |
| 836 else if (spawn_status < 0) | |
| 837 { | |
| 838 close(c2ppipe[0]); | |
| 839 Py_DECREF(testcase); | |
| 840 return NULL; | |
| 841 } | |
| 842 | |
| 843 // FIXME: use select in order not to miss SIGINT | |
| 844 while ((r = read(c2ppipe[0], &c, 1)) == -1 && errno == EINTR) | |
| 845 { | |
| 846 if (PyErr_CheckSignals() == -1) | |
| 847 { | |
| 848 PROPAGATE_SIGINT; | |
| 849 close(c2ppipe[0]); | |
| 850 Py_DECREF(testcase); | |
| 851 TERM_TESTEE; | |
| 852 return NULL; | |
| 853 } | |
| 854 } | |
| 855 if (r == 1) | |
| 856 { | |
| 857 if (c == TESTEE_SPAWNED) | |
| 858 { | |
| 859 size_t got = 0; | |
| 860 while (got < sizeof time_start) | |
| 861 { | |
| 862 r = read(c2ppipe[0], got + (char *) &time_start, sizeof time_start - got); | |
| 863 if (r > 0) | |
| 864 { | |
| 865 got += r; | |
| 866 } | |
| 867 else if (!r) | |
| 868 { | |
| 869 errno = 0; | |
| 870 PyErr_SetFromErrno(PyExc_IOError); | |
| 871 goto spawn_failed; | |
| 872 } | |
| 873 else if (errno == EINTR) | |
| 874 { | |
| 875 if (PyErr_CheckSignals() == -1) | |
| 876 { | |
| 877 PROPAGATE_SIGINT; | |
| 878 close(c2ppipe[0]); | |
| 879 Py_DECREF(testcase); | |
| 880 TERM_TESTEE; | |
| 881 return NULL; | |
| 882 } | |
| 883 } | |
| 884 else | |
| 885 { | |
| 886 PyErr_SetFromErrno(PyExc_IOError); | |
| 887 goto spawn_failed; | |
| 888 } | |
| 889 } | |
| 890 if (!timeval_to_attr(&time_start, testcase, "time_started")) | |
| 891 { | |
| 892 close(c2ppipe[0]); | |
| 893 Py_DECREF(testcase); | |
| 894 TERM_TESTEE; | |
| 895 return NULL; | |
| 896 } | |
| 897 } | |
| 898 else // if (c == TESTEE_SPAWN_FAILED) | |
| 899 { | |
| 900 size_t got = 0; | |
| 901 while (got < sizeof spawn_errno) | |
| 902 { | |
| 903 r = read(c2ppipe[0], got + (char *) &spawn_errno, sizeof spawn_errno - got); | |
| 904 if (r > 0) | |
| 905 { | |
| 906 got += r; | |
| 907 } | |
| 908 else if (!r) | |
| 909 { | |
| 910 // Can't get the real error; use zero instead | |
| 911 spawn_errno = 0; | |
| 912 break; | |
| 913 } | |
| 914 else if (errno == EINTR) | |
| 915 { | |
| 916 if (PyErr_CheckSignals() == -1) | |
| 917 { | |
| 918 PROPAGATE_SIGINT; | |
| 919 close(c2ppipe[0]); | |
| 920 Py_DECREF(testcase); | |
| 921 TERM_TESTEE; | |
| 922 return NULL; | |
| 923 } | |
| 924 } | |
| 925 else | |
| 926 { | |
| 927 PyErr_SetFromErrno(PyExc_IOError); | |
| 928 goto spawn_failed; | |
| 929 } | |
| 930 } | |
| 931 errno = spawn_errno; | |
| 932 /* | |
| 933 if (errno == EACCES || errno == EINVAL || errno == ELOOP | |
| 934 || errno == ENAMETOOLONG || errno == ENOENT || errno == ENOTDIR | |
| 935 || errno == ENOEXEC || errno == ETXTBSY) | |
| 936 { | |
| 937 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, PySequence_ITEM(args, 0)); | |
| 938 } | |
| 939 else | |
| 940 {*/ | |
| 941 PyErr_SetFromErrno(PyExc_OSError); | |
| 942 //} | |
| 943 goto spawn_failed; | |
| 944 } | |
| 945 } | |
| 946 else | |
| 947 { | |
| 948 PyObject *type, *value, *traceback, *e; | |
| 949 if (!r) errno = 0; | |
| 950 PyErr_SetFromErrno(PyExc_IOError); | |
| 951 spawn_failed: | |
| 952 Py_DECREF(testcase); | |
| 953 close(c2ppipe[0]); | |
| 954 TERM_TESTEE; | |
| 955 PyErr_Fetch(&type, &value, &traceback); | |
| 956 PyErr_NormalizeException(&type, &value, &traceback); | |
| 957 Py_XDECREF(traceback); | |
| 958 Py_DECREF(type); | |
| 959 e = PyObject_CallFunctionObjArgs(CannotStartTestee, value, NULL); | |
| 960 Py_DECREF(value); | |
| 961 PyErr_SetObject(CannotStartTestee, e); | |
| 962 Py_DECREF(e); | |
| 963 return NULL; | |
| 964 } | |
| 965 | |
| 966 Py_BEGIN_ALLOW_THREADS | |
| 967 timeradd(&time_start, &maxwalltime, &time_end); | |
| 968 FD_ZERO(&readfds); | |
| 969 have_maxwalltime = timerisset(&maxwalltime); | |
| 970 /* | |
| 971 Implementations may place limitations on the maximum timeout | |
| 972 interval supported. All implementations shall support a maximum | |
| 973 timeout interval of at least 31 days. If the timeout argument | |
| 974 specifies a timeout interval greater than the implementation- | |
| 975 defined maximum value, the maximum value shall be used as the | |
| 976 actual timeout value. | |
| 977 (POSIX:2008) | |
| 978 Therefore the loop and the && timercmp(&time_end, &now, <). | |
| 979 */ | |
| 980 for (;;) | |
| 981 { | |
| 982 _PyTime_timeval now; | |
| 983 int maxfd = c2ppipe[0]; | |
| 984 #ifdef HAVE_TERMIOS_H | |
| 985 if (catch_escape) FD_SET(0, &readfds); | |
| 986 #endif | |
| 987 #ifdef USE_WAKEUP_FD | |
| 988 FD_SET(intpipe[0], &readfds); | |
| 989 if (intpipe[0] > maxfd) maxfd = intpipe[0]; | |
| 990 #endif | |
| 991 FD_SET(c2ppipe[0], &readfds); | |
| 992 | |
| 993 if (have_maxwalltime) | |
| 994 { | |
| 995 _PyTime_gettimeofday(&now); | |
| 996 if (timercmp(&time_end, &now, <)) | |
| 997 { | |
| 998 timerclear(&timeout); | |
| 999 } | |
| 1000 else | |
| 1001 { | |
| 1002 timersub(&time_end, &now, &timeout); | |
| 1003 } | |
| 1004 | |
| 1005 s = select(maxfd + 1, &readfds, NULL, NULL, &timeout); | |
| 1006 | |
| 1007 if (!s && timercmp(&time_end, &now, <)) | |
| 1008 { | |
| 1009 close(c2ppipe[0]); | |
| 1010 TERM_TESTEE; | |
| 1011 Py_BLOCK_THREADS | |
| 1012 Py_DECREF(testcase); | |
| 1013 PyErr_SetObject(WallTimeLimitExceeded, NULL); | |
| 1014 return NULL; | |
| 1015 } | |
| 1016 } | |
| 1017 else | |
| 1018 { | |
| 1019 s = select(maxfd + 1, &readfds, NULL, NULL, NULL); | |
| 1020 } | |
| 1021 | |
| 1022 if (s < 0 && errno == EINTR) | |
| 1023 { | |
| 1024 Py_BLOCK_THREADS | |
| 1025 if (PyErr_CheckSignals() == -1) | |
| 1026 { | |
| 1027 PROPAGATE_SIGINT; | |
| 1028 close(c2ppipe[0]); | |
| 1029 Py_DECREF(testcase); | |
| 1030 TERM_TESTEE; | |
| 1031 return NULL; | |
| 1032 } | |
| 1033 Py_UNBLOCK_THREADS | |
| 1034 } | |
| 1035 else if (s < 0 && errno != EAGAIN) | |
| 1036 { | |
| 1037 Py_BLOCK_THREADS | |
| 1038 PyErr_SetFromErrno(PyExc_IOError); | |
| 1039 close(c2ppipe[0]); | |
| 1040 Py_DECREF(testcase); | |
| 1041 TERM_TESTEE; | |
| 1042 return NULL; | |
| 1043 } | |
| 1044 #ifdef USE_WAKEUP_FD | |
| 1045 else if (s > 0 && FD_ISSET(intpipe[0], &readfds)) | |
| 1046 { | |
| 1047 // FIXME: is error handling needed? | |
| 1048 while (read(intpipe[0], dont_care_buffer, sizeof dont_care_buffer) > 0); | |
| 1049 Py_BLOCK_THREADS | |
| 1050 if (PyErr_CheckSignals() == -1) | |
| 1051 { | |
| 1052 PROPAGATE_SIGINT; | |
| 1053 close(c2ppipe[0]); | |
| 1054 Py_DECREF(testcase); | |
| 1055 TERM_TESTEE; | |
| 1056 return NULL; | |
| 1057 } | |
| 1058 Py_UNBLOCK_THREADS | |
| 1059 } | |
| 1060 #endif | |
| 1061 #ifdef HAVE_TERMIOS_H | |
| 1062 else if (s > 0 && !FD_ISSET(c2ppipe[0], &readfds)) | |
| 1063 { | |
| 1064 // FIXME: is error and EOF handling needed? | |
| 1065 if ((r = read(0, &c, 1)) == 1) | |
| 1066 { | |
| 1067 if (c == '\33') | |
| 1068 { | |
| 1069 close(c2ppipe[0]); | |
| 1070 TERM_TESTEE; | |
| 1071 Py_BLOCK_THREADS | |
| 1072 Py_DECREF(testcase); | |
| 1073 PyErr_SetObject(CanceledByUser, NULL); | |
| 1074 return NULL; | |
| 1075 } | |
| 1076 } | |
| 1077 else if (r == -1 && errno == EINTR) | |
| 1078 { | |
| 1079 if (PyErr_CheckSignals() == -1) | |
| 1080 { | |
| 1081 PROPAGATE_SIGINT; | |
| 1082 close(c2ppipe[0]); | |
| 1083 Py_DECREF(testcase); | |
| 1084 TERM_TESTEE; | |
| 1085 return NULL; | |
| 1086 } | |
| 1087 } | |
| 1088 } | |
| 1089 #endif | |
| 1090 else if (s > 0) | |
| 1091 { | |
| 1092 bool blocked_threads = false; | |
| 1093 while ((r = read(c2ppipe[0], stats_read + (char *) &stats, sizeof stats - stats_read)) == -1 && errno == EINTR) | |
| 1094 { | |
| 1095 Py_BLOCK_THREADS | |
| 1096 blocked_threads = true; | |
| 1097 if (PyErr_CheckSignals() == -1) | |
| 1098 { | |
| 1099 PROPAGATE_SIGINT; | |
| 1100 close(c2ppipe[0]); | |
| 1101 Py_DECREF(testcase); | |
| 1102 TERM_TESTEE; | |
| 1103 return NULL; | |
| 1104 } | |
| 1105 } | |
| 1106 if (r > 0) | |
| 1107 { | |
| 1108 stats_read += r; | |
| 1109 } | |
| 1110 else if (!r) | |
| 1111 { | |
| 1112 break; | |
| 1113 } | |
| 1114 else | |
| 1115 { | |
| 1116 close(c2ppipe[0]); | |
| 1117 TERM_TESTEE; | |
| 1118 if (!blocked_threads) | |
| 1119 { | |
| 1120 Py_BLOCK_THREADS | |
| 1121 } | |
| 1122 Py_DECREF(testcase); | |
| 1123 PyErr_SetFromErrno(PyExc_IOError); | |
| 1124 return NULL; | |
| 1125 } | |
| 1126 if (blocked_threads) | |
| 1127 { | |
| 1128 Py_UNBLOCK_THREADS | |
| 1129 } | |
| 1130 } | |
| 1131 } | |
| 1132 close(c2ppipe[0]); | |
| 1133 Py_END_ALLOW_THREADS | |
| 1134 | |
| 1135 #ifdef HAVE_WAITPID | |
| 1136 while (waitpid(curpid, &retstat, 0) != curpid) | |
| 1137 #else | |
| 1138 while (wait(&retstat) != curpid) | |
| 1139 #endif | |
| 1140 { | |
| 1141 if (PyErr_CheckSignals() == -1) | |
| 1142 { | |
| 1143 Py_DECREF(testcase); | |
| 1144 return NULL; | |
| 1145 } | |
| 1146 } | |
| 1147 | |
| 1148 if (WIFEXITED(retstat) && WEXITSTATUS(retstat) == 127) | |
| 1149 { | |
| 1150 PyObject *type, *value, *traceback, *e; | |
| 1151 Py_DECREF(testcase); | |
| 1152 errno = 0; | |
| 1153 PyErr_SetFromErrno(PyExc_OSError); | |
| 1154 PyErr_Fetch(&type, &value, &traceback); | |
| 1155 PyErr_NormalizeException(&type, &value, &traceback); | |
| 1156 Py_XDECREF(traceback); | |
| 1157 Py_DECREF(type); | |
| 1158 e = PyObject_CallFunctionObjArgs(CannotStartTestee, value, NULL); | |
| 1159 Py_DECREF(value); | |
| 1160 PyErr_SetObject(CannotStartTestee, e); | |
| 1161 Py_DECREF(e); | |
| 1162 return NULL; | |
| 1163 } | |
| 1164 else if (!WIFEXITED(retstat) || WEXITSTATUS(retstat)) | |
| 1165 { | |
| 1166 Py_DECREF(testcase); | |
| 1167 if (WIFSTOPPED(retstat)) | |
| 1168 { | |
| 1169 return PyErr_Format(PyExc_EnvironmentError, "unexpected exit status from worker: stopped by signal %d", WSTOPSIG(retstat)); | |
| 1170 } | |
| 1171 else if (WIFSIGNALED(retstat)) | |
| 1172 { | |
| 1173 return PyErr_Format(PyExc_EnvironmentError, "unexpected exit status from worker: terminated by signal %d", WTERMSIG(retstat)); | |
| 1174 } | |
| 1175 else if (WIFEXITED(retstat)) | |
| 1176 { | |
| 1177 return PyErr_Format(PyExc_EnvironmentError, "unexpected exit status from worker: %d", WEXITSTATUS(retstat)); | |
| 1178 } | |
| 1179 else | |
| 1180 { | |
| 1181 PyErr_SetString(PyExc_EnvironmentError, "unexpected exit status from worker: not exited, signaled or stopped"); | |
| 1182 return NULL; | |
| 1183 } | |
| 1184 } | |
| 1185 | |
| 1186 if (stats_read != sizeof stats) | |
| 1187 { | |
| 1188 Py_DECREF(testcase); | |
| 1189 PyErr_SetString(PyExc_EnvironmentError, "unexpectedly early end of output from worker"); | |
| 1190 return NULL; | |
| 1191 } | |
| 1192 | |
| 1193 if (timerisset(&maxwalltime) && timercmp(&stats.walltime, &maxwalltime, >)) | |
| 1194 { | |
| 1195 Py_DECREF(testcase); | |
| 1196 PyErr_SetObject(WallTimeLimitExceeded, NULL); | |
| 1197 return NULL; | |
| 1198 } | |
| 1199 | |
| 1200 obj = PyInt_FromLong(0); | |
| 1201 if (obj == NULL) | |
| 1202 { | |
| 1203 Py_DECREF(testcase); | |
| 1204 return NULL; | |
| 1205 } | |
| 1206 if (PyObject_SetAttrString(testcase, "time_started", obj) == -1) | |
| 1207 { | |
| 1208 Py_DECREF(testcase); | |
| 1209 return NULL; | |
| 1210 } | |
| 1211 Py_DECREF(obj); | |
| 1212 | |
| 1213 #if defined HAVE_SYS_RESOURCE_H || defined HAVE_WAIT4 || defined HAVE_WAIT3 | |
| 1214 if (timerisset(&maxcputime) || !timerisset(&maxwalltime)) | |
| 1215 { | |
| 1216 PyObject *cputls; | |
| 1217 if (!timeval_to_attr(&stats.cputime, testcase, "time_stopped")) | |
| 1218 { | |
| 1219 Py_DECREF(testcase); | |
| 1220 return NULL; | |
| 1221 } | |
| 1222 cputls = PyObject_GetAttrString(testcase, "cpu_time_limit_string"); | |
| 1223 if (cputls == NULL) | |
| 1224 { | |
| 1225 Py_DECREF(testcase); | |
| 1226 return NULL; | |
| 1227 } | |
| 1228 if (PyObject_SetAttrString(testcase, "time_limit_string", cputls) == -1) | |
| 1229 { | |
| 1230 Py_DECREF(testcase); | |
| 1231 return NULL; | |
| 1232 } | |
| 1233 Py_DECREF(cputls); | |
| 1234 if (timerisset(&maxcputime) && timercmp(&stats.cputime, &maxcputime, >)) | |
| 1235 { | |
| 1236 Py_DECREF(testcase); | |
| 1237 PyErr_SetObject(CPUTimeLimitExceeded, NULL); | |
| 1238 return NULL; | |
| 1239 } | |
| 1240 } | |
| 1241 else | |
| 1242 #endif | |
| 1243 { | |
| 1244 if (!timeval_to_attr(&stats.walltime, testcase, "time_stopped")) | |
| 1245 { | |
| 1246 Py_DECREF(testcase); | |
| 1247 return NULL; | |
| 1248 } | |
| 1249 } | |
| 1250 | |
| 1251 #if defined HAVE_SYS_RESOURCE_H || defined HAVE_WAIT4 || defined HAVE_WAIT3 | |
| 1252 if (maxmemory && stats.memory > maxmemory) | |
| 1253 { | |
| 1254 Py_DECREF(testcase); | |
| 1255 PyErr_SetObject(MemoryLimitExceeded, NULL); | |
| 1256 return NULL; | |
| 1257 } | |
| 1258 #endif | |
| 1259 | |
| 1260 Popen_placeholder = PyObject_New(_unix__PopenPlaceholderObject, &_unix__PopenPlaceholderType); | |
| 1261 if (Popen_placeholder == NULL) | |
| 1262 { | |
| 1263 return NULL; | |
| 1264 } | |
| 1265 Popen_placeholder->returncode = stats.returncode; | |
| 1266 PyObject_SetAttrString(testcase, "process", (PyObject *) Popen_placeholder); | |
| 1267 Py_DECREF(Popen_placeholder); | |
| 1268 Py_DECREF(testcase); | |
| 1269 Py_RETURN_NONE; | |
| 1270 } | |
| 1271 | |
| 1272 static PyObject *_unix_pause(PyObject *self) | |
| 1273 { | |
| 1274 #ifdef HAVE_TERMIOS_H | |
| 1275 if (catch_escape) | |
| 1276 { | |
| 1277 char c; | |
| 1278 while (read(0, &c, 1) == -1 && errno == EINTR); | |
| 1279 } | |
| 1280 #endif | |
| 1281 Py_RETURN_NONE; | |
| 1282 } | |
| 1283 | |
| 1284 static PyMethodDef _unixMethods[] = | |
| 1285 { | |
| 1286 { "call", (PyCFunction) _unix_call, METH_VARARGS | METH_KEYWORDS, "Call a process." }, | |
| 1287 { "pause", (PyCFunction) _unix_pause, METH_NOARGS, "Block until a key is pressed." }, | |
| 1288 { NULL } | |
| 1289 }; | |
| 1290 | |
| 1291 #ifdef USE_WAKEUP_FD | |
| 1292 static void close_intpipe(void) | |
| 1293 { | |
| 1294 close(intpipe[0]); | |
| 1295 close(intpipe[1]); | |
| 1296 intpipe[0] = intpipe[1] = 0; | |
| 1297 } | |
| 1298 #endif | |
| 1299 | |
| 1300 #ifdef HAVE_TERMIOS_H | |
| 1301 static void restore_termios(void) | |
| 1302 { | |
| 1303 tcsetattr(0, TCSAFLUSH, &orig_termios); | |
| 1304 #ifdef USE_WAKEUP_FD | |
| 1305 close_intpipe(); | |
| 1306 #endif | |
| 1307 } | |
| 1308 #endif | |
| 1309 | |
| 1310 #if PY_MAJOR_VERSION >= 3 | |
| 1311 #define INIT_FAIL return NULL | |
| 1312 static PyModuleDef _unixmodule = | |
| 1313 { | |
| 1314 PyModuleDef_HEAD_INIT, | |
| 1315 "_unix", | |
| 1316 NULL, | |
| 1317 -1, | |
| 1318 _unixMethods | |
| 1319 }; | |
| 1320 | |
| 1321 PyMODINIT_FUNC PyInit__unix(void) | |
| 1322 #else | |
| 1323 #define INIT_FAIL return | |
| 1324 PyMODINIT_FUNC init_unix(void) | |
| 1325 #endif | |
| 1326 { | |
| 1327 struct termios new_termios; | |
| 1328 PyObject *testcases; | |
| 1329 | |
| 1330 _unix__PopenPlaceholderType.tp_new = PyType_GenericNew; | |
| 1331 if (PyType_Ready(&_unix__PopenPlaceholderType) == -1) | |
| 1332 { | |
| 1333 INIT_FAIL; | |
| 1334 } | |
| 1335 | |
| 1336 testcases = PyImport_ImportModule("testcases"); | |
| 1337 if (testcases == NULL) | |
| 1338 { | |
| 1339 INIT_FAIL; | |
| 1340 } | |
| 1341 if ((CannotStartTestee = PyObject_GetAttrString(testcases, "CannotStartTestee")) == NULL | |
| 1342 || (CanceledByUser = PyObject_GetAttrString(testcases, "CanceledByUser")) == NULL | |
| 1343 || (WallTimeLimitExceeded = PyObject_GetAttrString(testcases, "WallTimeLimitExceeded")) == NULL | |
| 1344 || (CPUTimeLimitExceeded = PyObject_GetAttrString(testcases, "CPUTimeLimitExceeded")) == NULL | |
| 1345 || (MemoryLimitExceeded = PyObject_GetAttrString(testcases, "MemoryLimitExceeded")) == NULL) | |
| 1346 { | |
| 1347 Py_XDECREF(MemoryLimitExceeded); | |
| 1348 Py_XDECREF(CPUTimeLimitExceeded); | |
| 1349 Py_XDECREF(WallTimeLimitExceeded); | |
| 1350 Py_XDECREF(CanceledByUser); | |
| 1351 Py_XDECREF(CannotStartTestee); | |
| 1352 Py_DECREF(testcases); | |
| 1353 INIT_FAIL; | |
| 1354 } | |
| 1355 Py_DECREF(testcases); | |
| 1356 | |
| 1357 #ifdef WITH_NEXT_FRAMEWORK | |
| 1358 if (environ == NULL) | |
| 1359 { | |
| 1360 environ = *_NSGetEnviron(); | |
| 1361 } | |
| 1362 #endif | |
| 1363 | |
| 1364 #ifdef USE_WAKEUP_FD | |
| 1365 if (!intpipe[0] || !intpipe[1]) | |
| 1366 { | |
| 1367 #ifdef HAVE_PIPE2 | |
| 1368 if (pipe2(intpipe, O_CLOEXEC | O_NONBLOCK)) | |
| 1369 { | |
| 1370 PyErr_SetFromErrno(PyExc_IOError); | |
| 1371 Py_DECREF(MemoryLimitExceeded); | |
| 1372 Py_DECREF(CPUTimeLimitExceeded); | |
| 1373 Py_DECREF(WallTimeLimitExceeded); | |
| 1374 Py_DECREF(CanceledByUser); | |
| 1375 Py_DECREF(CannotStartTestee); | |
| 1376 INIT_FAIL; | |
| 1377 } | |
| 1378 #else | |
| 1379 if (pipe(intpipe)) | |
| 1380 { | |
| 1381 PyErr_SetFromErrno(PyExc_IOError); | |
| 1382 Py_DECREF(MemoryLimitExceeded); | |
| 1383 Py_DECREF(CPUTimeLimitExceeded); | |
| 1384 Py_DECREF(WallTimeLimitExceeded); | |
| 1385 Py_DECREF(CanceledByUser); | |
| 1386 Py_DECREF(CannotStartTestee); | |
| 1387 INIT_FAIL; | |
| 1388 } | |
| 1389 // Other threads must not fork now | |
| 1390 if (fcntl(intpipe[0], F_SETFD, fcntl(intpipe[0], F_GETFD) | FD_CLOEXEC) == -1 | |
| 1391 || fcntl(intpipe[1], F_SETFD, fcntl(intpipe[1], F_GETFD) | FD_CLOEXEC) == -1 | |
| 1392 || fcntl(intpipe[0], F_SETFL, fcntl(intpipe[0], F_GETFL) | O_NONBLOCK) == -1 | |
| 1393 || fcntl(intpipe[1], F_SETFL, fcntl(intpipe[1], F_GETFL) | O_NONBLOCK) == -1) | |
| 1394 { | |
| 1395 PyErr_SetFromErrno(PyExc_IOError); | |
| 1396 close(intpipe[0]); | |
| 1397 close(intpipe[1]); | |
| 1398 Py_DECREF(MemoryLimitExceeded); | |
| 1399 Py_DECREF(CPUTimeLimitExceeded); | |
| 1400 Py_DECREF(WallTimeLimitExceeded); | |
| 1401 Py_DECREF(CanceledByUser); | |
| 1402 Py_DECREF(CannotStartTestee); | |
| 1403 INIT_FAIL; | |
| 1404 } | |
| 1405 #endif | |
| 1406 } | |
| 1407 | |
| 1408 PySignal_SetWakeupFd(intpipe[1]); | |
| 1409 #endif | |
| 1410 | |
| 1411 #ifdef HAVE_TERMIOS_H | |
| 1412 if (!tcgetattr(0, &orig_termios)) | |
| 1413 { | |
| 1414 new_termios = orig_termios; | |
| 1415 // Stolen from tty.py of Python 2.7.1 | |
| 1416 new_termios.c_lflag &= ~(ECHO | ICANON); | |
| 1417 new_termios.c_cc[VMIN] = 1; | |
| 1418 new_termios.c_cc[VTIME] = 0; | |
| 1419 if (!Py_AtExit(restore_termios) && !tcsetattr(0, TCSAFLUSH, &new_termios)) | |
| 1420 { | |
| 1421 catch_escape = true; | |
| 1422 } | |
| 1423 } | |
| 1424 #ifdef USE_WAKEUP_FD | |
| 1425 else | |
| 1426 { | |
| 1427 Py_AtExit(close_intpipe); | |
| 1428 } | |
| 1429 #endif | |
| 1430 #elif defined USE_WAKEUP_FD | |
| 1431 Py_AtExit(close_intpipe); | |
| 1432 #endif | |
| 1433 | |
| 1434 #if PY_MAJOR_VERSION >= 3 | |
| 1435 PyObject *module = PyModule_Create(&_unixmodule); | |
| 1436 if (module == NULL) | |
| 1437 { | |
| 1438 Py_DECREF(MemoryLimitExceeded); | |
| 1439 Py_DECREF(CPUTimeLimitExceeded); | |
| 1440 Py_DECREF(WallTimeLimitExceeded); | |
| 1441 Py_DECREF(CanceledByUser); | |
| 1442 Py_DECREF(CannotStartTestee); | |
| 1443 } | |
| 1444 return module; | |
| 1445 #else | |
| 1446 Py_InitModule("_unix", _unixMethods); | |
| 1447 #endif | |
| 1448 } |
