comparison upreckon/_unixmodule.cpp @ 146:d5b6708c1955

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