File: | src/gnu/usr.bin/binutils/obj/gdb/conftest.c |
Warning: | line 34, column 13 This function call is prohibited after a successful vfork |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | #line 6483 "configure" | |||
2 | #include "confdefs.h" | |||
3 | /* Thanks to Paul Eggert for this test. */ | |||
4 | #include <stdio.h> | |||
5 | #include <sys/types.h> | |||
6 | #include <sys/stat.h> | |||
7 | #ifdef HAVE_UNISTD_H1 | |||
8 | #include <unistd.h> | |||
9 | #endif | |||
10 | #ifdef HAVE_VFORK_H | |||
11 | #include <vfork.h> | |||
12 | #endif | |||
13 | /* On some sparc systems, changes by the child to local and incoming | |||
14 | argument registers are propagated back to the parent. | |||
15 | The compiler is told about this with #include <vfork.h>, | |||
16 | but some compilers (e.g. gcc -O) don't grok <vfork.h>. | |||
17 | Test for this by using a static variable whose address | |||
18 | is put into a register that is clobbered by the vfork. */ | |||
19 | static | |||
20 | #ifdef __cplusplus | |||
21 | sparc_address_test (int arg) | |||
22 | #else | |||
23 | sparc_address_test (arg) int arg; | |||
24 | #endif | |||
25 | { | |||
26 | static pid_t child; | |||
27 | if (!child
| |||
| ||||
28 | child = vfork (); | |||
29 | if (child
| |||
30 | perror ("vfork"); | |||
31 | _exit(2); | |||
32 | } | |||
33 | if (!child
| |||
34 | arg = getpid(); | |||
| ||||
35 | write(-1, "", 0); | |||
36 | _exit (arg); | |||
37 | } | |||
38 | } | |||
39 | } | |||
40 | main() { | |||
41 | pid_t parent = getpid (); | |||
42 | pid_t child; | |||
43 | ||||
44 | sparc_address_test (); | |||
45 | ||||
46 | child = vfork (); | |||
47 | ||||
48 | if (child == 0) { | |||
49 | /* Here is another test for sparc vfork register problems. | |||
50 | This test uses lots of local variables, at least | |||
51 | as many local variables as main has allocated so far | |||
52 | including compiler temporaries. 4 locals are enough for | |||
53 | gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. | |||
54 | A buggy compiler should reuse the register of parent | |||
55 | for one of the local variables, since it will think that | |||
56 | parent can't possibly be used any more in this routine. | |||
57 | Assigning to the local variable will thus munge parent | |||
58 | in the parent process. */ | |||
59 | pid_t | |||
60 | p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), | |||
61 | p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); | |||
62 | /* Convince the compiler that p..p7 are live; otherwise, it might | |||
63 | use the same hardware register for all 8 local variables. */ | |||
64 | if (p != p1 || p != p2 || p != p3 || p != p4 | |||
65 | || p != p5 || p != p6 || p != p7) | |||
66 | _exit(1); | |||
67 | ||||
68 | /* On some systems (e.g. IRIX 3.3), | |||
69 | vfork doesn't separate parent from child file descriptors. | |||
70 | If the child closes a descriptor before it execs or exits, | |||
71 | this munges the parent's descriptor as well. | |||
72 | Test for this by closing stdout in the child. */ | |||
73 | _exit(close(fileno(stdout)(!__isthreaded ? (((&__sF[1]))->_file) : (fileno)((& __sF[1])))) != 0); | |||
74 | } else { | |||
75 | int status; | |||
76 | struct stat st; | |||
77 | ||||
78 | while (wait(&status) != child) | |||
79 | ; | |||
80 | exit( | |||
81 | /* Was there some problem with vforking? */ | |||
82 | child < 0 | |||
83 | ||||
84 | /* Did the child fail? (This shouldn't happen.) */ | |||
85 | || status | |||
86 | ||||
87 | /* Did the vfork/compiler bug occur? */ | |||
88 | || parent != getpid() | |||
89 | ||||
90 | /* Did the file descriptor bug occur? */ | |||
91 | || fstat(fileno(stdout)(!__isthreaded ? (((&__sF[1]))->_file) : (fileno)((& __sF[1]))), &st) != 0 | |||
92 | ); | |||
93 | } | |||
94 | } |