/[meta-cvs]/meta-cvs/F-83F0E6A90D5BBCDFB58440970E850925.c
ViewVC logotype

Contents of /meta-cvs/F-83F0E6A90D5BBCDFB58440970E850925.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4.2.10 - (show annotations)
Wed Feb 26 03:53:28 2003 UTC (11 years, 1 month ago) by kaz
Branch: mcvs-1-0-branch
CVS Tags: mcvs-1-0-5, mcvs-1-0-6
Changes since 1.4.2.9: +4 -2 lines
File MIME type: text/plain
* code/unix-bindings/wrap.c (mcvs_spawn): One more waitpid() bug!
The SIGCHLD signal handler was being set in the child process only,
so although we fixed the waitpid() behavior in the CVS child
process, we did not fix it in the Meta-CVS process. The ECHILD
problem was sporadically reproduced by Johannes Grødem on a fast
Athlon machine; it requires CVS to exit before Meta-CVS reaches
the waitpid() call.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <signal.h>
6 #include <dirent.h>
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <sys/wait.h>
11 #ifdef __CYGWIN__
12 #include <process.h>
13 #endif
14
15 /*
16 * Null pointer test
17 */
18
19 int mcvs_null_pointer_p(void *ptr)
20 {
21 return ptr == 0;
22 }
23
24 /*
25 * <errno.h> stuff
26 */
27
28 int mcvs_get_errno(void)
29 {
30 return errno;
31 }
32
33 int mcvs_set_errno(int value)
34 {
35 return errno = value;
36 }
37
38 /*
39 * <dirent.h> stuff
40 */
41
42 typedef struct {
43 unsigned long d_ino;
44 char d_name[1024];
45 } mcvs_dirent;
46
47 mcvs_dirent *mcvs_readdir(DIR *dir)
48 {
49 static mcvs_dirent dw;
50 struct dirent *de = readdir(dir);
51 if (de != 0) {
52 strncpy(dw.d_name, de->d_name, sizeof dw.d_name - 1);
53 dw.d_ino = de->d_ino;
54 return &dw;
55 }
56 return 0;
57 }
58
59 /*
60 * <unistd.h> stuff
61 */
62
63 char *mcvs_readlink(const char *path)
64 {
65 size_t size = 256;
66 char *str = malloc(size);
67 char *temp;
68
69 if (str == 0)
70 goto bail;
71
72 for (;;) {
73 int result = readlink(path, str, size);
74 if (result == -1)
75 goto bail;
76 if (result < size) {
77 str[result] = 0;
78 break;
79 }
80 if (size * 2 < size)
81 goto bail;
82 size *= 2;
83 if ((temp = realloc(str, size)) == 0)
84 goto bail;
85 str = temp;
86 }
87
88 /* No need to realloc to actual size, since CLISP will free this anyway */
89 return str;
90
91 bail:
92 free(str);
93 return 0;
94 }
95
96 /*
97 * <sys/stat.h> stuff
98 */
99
100 struct mcvs_stat {
101 unsigned long dev;
102 unsigned long ino;
103 unsigned long mode;
104 unsigned int nlink;
105 unsigned int uid;
106 unsigned int gid;
107 unsigned long rdev;
108 unsigned long blksize;
109 unsigned long blocks;
110 unsigned long atime;
111 unsigned long mtime;
112 unsigned long ctime;
113 };
114
115 static void stat_to_wrap(struct mcvs_stat *out, const struct stat *in)
116 {
117 out->dev = in->st_dev;
118 out->ino = in->st_ino;
119 out->mode = in->st_mode;
120 out->nlink = in->st_nlink;
121 out->uid = in->st_uid;
122 out->gid = in->st_gid;
123 out->rdev = in->st_rdev;
124 out->blksize = in->st_blksize;
125 out->blocks = in->st_blocks;
126 out->atime = in->st_atime;
127 out->mtime = in->st_mtime;
128 out->ctime = in->st_ctime;
129 }
130
131 #define IMPL_STAT(FUNC, ARGTYPE) \
132 int mcvs_ ## FUNC(ARGTYPE arg, struct mcvs_stat *buf) \
133 { \
134 struct stat sbuf; \
135 int retval = FUNC(arg, &sbuf); \
136 if (retval == 0) \
137 stat_to_wrap(buf, &sbuf); \
138 return retval; \
139 }
140
141 IMPL_STAT(stat, const char *)
142 IMPL_STAT(lstat, const char *)
143 IMPL_STAT(fstat, int)
144
145 /*
146 * <unistd.h> -- getcwd
147 */
148
149 const char *mcvs_getcwd(void)
150 {
151 size_t size = 256;
152 char *str = malloc(size);
153 char *temp;
154
155 if (str == 0)
156 goto bail;
157
158 while (getcwd(str, size) == 0) {
159 if (errno != ERANGE)
160 goto bail;
161 if (size * 2 < size)
162 goto bail;
163 size *= 2;
164 if ((temp = realloc(str, size)) == 0)
165 goto bail;
166 str = temp;
167 }
168
169 /* No need to realloc to actual size, since CLISP will free this anyway */
170 return str;
171
172 bail:
173 free(str);
174 return 0;
175 }
176
177 /*
178 * We need this because CLISP sets it to SIG_IGN, which is
179 * inherited by the exec'd image, and causes the wait()
180 * functions to have behavior that programs don't expect.
181 */
182
183 void mcvs_default_sigchld()
184 {
185 signal(SIGCHLD, SIG_DFL);
186 }
187
188 /*
189 * <unistd.h> -- fork, wait*, exec*
190 */
191
192 #ifdef __CYGWIN__
193 /*
194 * On Cygwin, we have a straightforward alternative to fork exec
195 * and wait, so let's use it.
196 */
197
198 int mcvs_spawn(const char *name, const char *const *argv)
199 {
200 return spawnvp(_P_WAIT, name, argv);
201 }
202 #else
203 int mcvs_spawn(const char *name, char *const *argv)
204 {
205 int result = -1;
206 int status = 0;
207 pid_t child;
208
209 mcvs_default_sigchld();
210
211 child = fork();
212
213 if (child == -1)
214 goto out;
215
216 if (child == 0) {
217 execvp(name, argv);
218 _exit(EXIT_FAILURE);
219 }
220
221 do {
222 result = waitpid(child, &status, 0);
223 } while (result == -1 && errno == EINTR);
224
225 if (result == -1)
226 goto out;
227
228 if (WIFEXITED(status))
229 result = WEXITSTATUS(status);
230
231 out:
232 free((void *) argv);
233 return result;
234 }
235 #endif

  ViewVC Help
Powered by ViewVC 1.1.5