Print this page
make: unifdef for REDIRECT_ERR (defined)
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/make/bin/dist.cc
+++ new/usr/src/cmd/make/bin/dist.cc
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #ifdef DISTRIBUTED
27 27 /*
28 28 * dist.cc
29 29 *
30 30 * Deal with the distributed processing
31 31 */
32 32
33 33 #include <avo/err.h>
34 34 #include <avo/find_dir.h>
35 35 #include <avo/util.h>
36 36 #include <dm/Avo_AcknowledgeMsg.h>
37 37 #include <dm/Avo_DoJobMsg.h>
38 38 #include <dm/Avo_JobResultMsg.h>
39 39 #include <mk/defs.h>
40 40 #include <mksh/misc.h> /* getmem() */
41 41 #include <rw/pstream.h>
42 42 #include <rw/queuecol.h>
43 43 #include <rw/xdrstrea.h>
44 44 #include <signal.h>
45 45 #include <strstream.h>
46 46 #include <sys/stat.h> /* stat() */
47 47 #include <sys/types.h>
48 48 #include <sys/wait.h>
49 49 #include <unistd.h>
50 50 #include <errno.h>
51 51
52 52 /*
53 53 * Defined macros
54 54 */
55 55
56 56 #define AVO_BLOCK_INTERUPTS sigfillset(&newset) ; \
57 57 sigprocmask(SIG_SETMASK, &newset, &oldset)
58 58
59 59 #define AVO_UNBLOCK_INTERUPTS \
60 60 sigprocmask(SIG_SETMASK, &oldset, &newset)
61 61
62 62
63 63 /*
64 64 * typedefs & structs
65 65 */
66 66
67 67 /*
68 68 * Static variables
69 69 */
70 70 int dmake_ifd;
71 71 FILE* dmake_ifp;
72 72 XDR xdrs_in;
73 73
74 74 int dmake_ofd;
75 75 FILE* dmake_ofp;
76 76 XDR xdrs_out;
77 77
78 78 // These instances are required for the RWfactory.
79 79 static Avo_JobResultMsg dummyJobResultMsg;
80 80 static Avo_AcknowledgeMsg dummyAcknowledgeMsg;
81 81 static int firstAcknowledgeReceived = 0;
82 82
83 83 int rxmPid = 0;
84 84
85 85 /*
86 86 * File table of contents
87 87 */
88 88 static void set_dmake_env_vars(void);
89 89
90 90 /*
91 91 * void
92 92 * startup_rxm(void)
93 93 *
94 94 * When startup_rxm() is called, read_command_options() and
95 95 * read_files_and_state() have already been read, so DMake
96 96 * will now know what options to pass to rxm.
97 97 *
98 98 * rxm
99 99 * [ -k ] [ -n ]
100 100 * [ -c <dmake_rcfile> ]
101 101 * [ -g <dmake_group> ]
102 102 * [ -j <dmake_max_jobs> ]
103 103 * [ -m <dmake_mode> ]
104 104 * [ -o <dmake_odir> ]
105 105 * <read_fd> <write_fd>
106 106 *
107 107 * rxm will, among other things, read the rc file.
108 108 *
109 109 */
110 110 void
111 111 startup_rxm(void)
112 112 {
113 113 Name dmake_name;
114 114 Name dmake_value;
115 115 Avo_err *find_run_dir_err;
116 116 int pipe1[2], pipe2[2];
117 117 Property prop;
118 118 char *run_dir;
119 119 char rxm_command[MAXPATHLEN];
120 120 int rxm_debug = 0;
121 121
122 122 int length;
123 123 char * env;
124 124
125 125 firstAcknowledgeReceived = 0;
126 126 /*
127 127 * Create two pipes, one for dmake->rxm, and one for rxm->dmake.
128 128 * pipe1 is dmake->rxm,
129 129 * pipe2 is rxm->dmake.
130 130 */
131 131 if ((pipe(pipe1) < 0) || (pipe(pipe2) < 0)) {
132 132 fatal(catgets(catd, 1, 245, "pipe() failed: %s"), errmsg(errno));
133 133 }
134 134
135 135 set_dmake_env_vars();
136 136
137 137 if ((rxmPid = fork()) < 0) { /* error */
138 138 fatal(catgets(catd, 1, 246, "fork() failed: %s"), errmsg(errno));
139 139 } else if (rxmPid > 0) { /* parent, dmake */
140 140 dmake_ofd = pipe1[1]; // write side of pipe
141 141 if (!(dmake_ofp = fdopen(dmake_ofd, "a"))) {
142 142 fatal(catgets(catd, 1, 247, "fdopen() failed: %s"), errmsg(errno));
143 143 }
144 144 xdrstdio_create(&xdrs_out, dmake_ofp, XDR_ENCODE);
145 145
146 146 dmake_ifd = pipe2[0]; // read side of pipe
147 147 if (!(dmake_ifp = fdopen(dmake_ifd, "r"))) {
148 148 fatal(catgets(catd, 1, 248, "fdopen() failed: %s"), errmsg(errno));
149 149 }
150 150 xdrstdio_create(&xdrs_in, dmake_ifp, XDR_DECODE);
151 151
152 152 close(pipe1[0]); // read side
153 153 close(pipe2[1]); // write side
154 154 } else { /* child, rxm */
155 155 close(pipe1[1]); // write side
156 156 close(pipe2[0]); // read side
157 157
158 158 /* Find the run directory of dmake, for rxm. */
159 159 find_run_dir_err = avo_find_run_dir(&run_dir);
160 160 if (find_run_dir_err) {
161 161 delete find_run_dir_err;
162 162 /* Use the path to find rxm. */
163 163 (void) sprintf(rxm_command, NOCATGETS("rxm"));
164 164 } else {
165 165 /* Use the run dir of dmake for rxm. */
166 166 (void) sprintf(rxm_command, NOCATGETS("%s/rxm"), run_dir);
167 167 }
168 168
169 169 if (continue_after_error) {
170 170 (void) strcat(rxm_command, NOCATGETS(" -k"));
171 171 }
172 172 if (do_not_exec_rule) {
173 173 (void) strcat(rxm_command, NOCATGETS(" -n"));
174 174 }
175 175 if (rxm_debug) {
176 176 (void) strcat(rxm_command, NOCATGETS(" -S"));
177 177 }
178 178 if (send_mtool_msgs) {
179 179 (void) sprintf(&rxm_command[strlen(rxm_command)],
180 180 NOCATGETS(" -O %d"),
181 181 mtool_msgs_fd);
182 182 }
183 183 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE"));
184 184 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
185 185 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
186 186 ((dmake_value = prop->body.macro.value) != NULL)) {
187 187 (void) sprintf(&rxm_command[strlen(rxm_command)],
188 188 NOCATGETS(" -c %s"),
189 189 dmake_value->string_mb);
190 190 } else {
191 191 length = 2 + strlen(NOCATGETS("DMAKE_RCFILE"));
192 192 env = getmem(length);
193 193 (void) sprintf(env,
194 194 "%s=",
195 195 NOCATGETS("DMAKE_RCFILE"));
196 196 (void) putenv(env);
197 197 }
198 198 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP"));
199 199 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
200 200 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
201 201 ((dmake_value = prop->body.macro.value) != NULL)) {
202 202 (void) sprintf(&rxm_command[strlen(rxm_command)],
203 203 NOCATGETS(" -g %s"),
204 204 dmake_value->string_mb);
205 205 } else {
206 206 length = 2 + strlen(NOCATGETS("DMAKE_GROUP"));
207 207 env = getmem(length);
208 208 (void) sprintf(env,
209 209 "%s=",
210 210 NOCATGETS("DMAKE_GROUP"));
211 211 (void) putenv(env);
212 212 }
213 213 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS"));
214 214 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
215 215 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
216 216 ((dmake_value = prop->body.macro.value) != NULL)) {
217 217 (void) sprintf(&rxm_command[strlen(rxm_command)],
218 218 NOCATGETS(" -j %s"),
219 219 dmake_value->string_mb);
220 220 } else {
221 221 length = 2 + strlen(NOCATGETS("DMAKE_MAX_JOBS"));
222 222 env = getmem(length);
223 223 (void) sprintf(env,
224 224 "%s=",
225 225 NOCATGETS("DMAKE_MAX_JOBS"));
226 226 (void) putenv(env);
227 227 }
228 228 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE"));
229 229 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
230 230 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
231 231 ((dmake_value = prop->body.macro.value) != NULL)) {
232 232 (void) sprintf(&rxm_command[strlen(rxm_command)],
233 233 NOCATGETS(" -m %s"),
234 234 dmake_value->string_mb);
235 235 } else {
236 236 length = 2 + strlen(NOCATGETS("DMAKE_MODE"));
237 237 env = getmem(length);
238 238 (void) sprintf(env,
239 239 "%s=",
240 240 NOCATGETS("DMAKE_MODE"));
241 241 (void) putenv(env);
242 242 }
243 243 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR"));
244 244 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
245 245 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
246 246 ((dmake_value = prop->body.macro.value) != NULL)) {
247 247 (void) sprintf(&rxm_command[strlen(rxm_command)],
248 248 NOCATGETS(" -o %s"),
249 249 dmake_value->string_mb);
250 250 } else {
251 251 length = 2 + strlen(NOCATGETS("DMAKE_ODIR"));
252 252 env = getmem(length);
253 253 (void) sprintf(env,
254 254 "%s=",
255 255 NOCATGETS("DMAKE_ODIR"));
256 256 (void) putenv(env);
257 257 }
258 258
259 259 (void) sprintf(&rxm_command[strlen(rxm_command)],
260 260 NOCATGETS(" %d %d"),
261 261 pipe1[0], pipe2[1]);
262 262 execl(NOCATGETS("/usr/bin/sh"),
263 263 NOCATGETS("sh"),
264 264 NOCATGETS("-c"),
265 265 rxm_command,
266 266 (char *)NULL);
267 267 _exit(127);
268 268 }
269 269 }
270 270
271 271 /*
272 272 * static void
273 273 * set_dmake_env_vars()
274 274 *
275 275 * Sets the DMAKE_* environment variables for rxm and rxs.
276 276 * DMAKE_PWD
277 277 * DMAKE_NPWD
278 278 * DMAKE_UMASK
279 279 * DMAKE_SHELL
280 280 */
281 281 static void
282 282 set_dmake_env_vars()
283 283 {
284 284 char *current_netpath;
↓ open down ↓ |
284 lines elided |
↑ open up ↑ |
285 285 char *current_path;
286 286 static char *env;
287 287 int length;
288 288 char netpath[MAXPATHLEN];
289 289 mode_t um;
290 290 char um_buf[MAXPATHLEN];
291 291 Name dmake_name;
292 292 Name dmake_value;
293 293 Property prop;
294 294
295 -#ifdef REDIRECT_ERR
296 295 /* Set __DMAKE_REDIRECT_STDERR */
297 296 length = 2 + strlen(NOCATGETS("__DMAKE_REDIRECT_STDERR")) + 1;
298 297 env = getmem(length);
299 298 (void) sprintf(env,
300 299 "%s=%s",
301 300 NOCATGETS("__DMAKE_REDIRECT_STDERR"),
302 301 out_err_same ? NOCATGETS("0") : NOCATGETS("1"));
303 302 (void) putenv(env);
304 -#endif
305 303
306 304 /* Set DMAKE_PWD to the current working directory */
307 305 current_path = get_current_path();
308 306 length = 2 + strlen(NOCATGETS("DMAKE_PWD")) + strlen(current_path);
309 307 env = getmem(length);
310 308 (void) sprintf(env,
311 309 "%s=%s",
312 310 NOCATGETS("DMAKE_PWD"),
313 311 current_path);
314 312 (void) putenv(env);
315 313
316 314 /* Set DMAKE_NPWD to machine:pathname */
317 315 if (avo_path_to_netpath(current_path, netpath)) {
318 316 current_netpath = netpath;
319 317 } else {
320 318 current_netpath = current_path;
321 319 }
322 320 length = 2 + strlen(NOCATGETS("DMAKE_NPWD")) + strlen(current_netpath);
323 321 env = getmem(length);
324 322 (void) sprintf(env,
325 323 "%s=%s",
326 324 NOCATGETS("DMAKE_NPWD"),
327 325 current_netpath);
328 326 (void) putenv(env);
329 327
330 328 /* Set DMAKE_UMASK to the value of umask */
331 329 um = umask(0);
332 330 umask(um);
333 331 (void) sprintf(um_buf, NOCATGETS("%ul"), um);
334 332 length = 2 + strlen(NOCATGETS("DMAKE_UMASK")) + strlen(um_buf);
335 333 env = getmem(length);
336 334 (void) sprintf(env,
337 335 "%s=%s",
338 336 NOCATGETS("DMAKE_UMASK"),
339 337 um_buf);
340 338 (void) putenv(env);
341 339
342 340 if (((prop = get_prop(shell_name->prop, macro_prop)) != NULL) &&
343 341 ((dmake_value = prop->body.macro.value) != NULL)) {
344 342 length = 2 + strlen(NOCATGETS("DMAKE_SHELL")) +
345 343 strlen(dmake_value->string_mb);
346 344 env = getmem(length);
347 345 (void) sprintf(env,
348 346 "%s=%s",
349 347 NOCATGETS("DMAKE_SHELL"),
350 348 dmake_value->string_mb);
351 349 (void) putenv(env);
352 350 }
353 351 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE"));
354 352 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
355 353 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
356 354 ((dmake_value = prop->body.macro.value) != NULL)) {
357 355 length = 2 + strlen(NOCATGETS("DMAKE_OUTPUT_MODE")) +
358 356 strlen(dmake_value->string_mb);
359 357 env = getmem(length);
360 358 (void) sprintf(env,
361 359 "%s=%s",
362 360 NOCATGETS("DMAKE_OUTPUT_MODE"),
363 361 dmake_value->string_mb);
364 362 (void) putenv(env);
365 363 }
366 364 }
367 365
368 366 /*
369 367 * void
370 368 * distribute_rxm(Avo_DoJobMsg *dmake_job_msg)
371 369 *
372 370 * Write the DMake rule to be distributed down the pipe to rxm.
373 371 *
374 372 */
375 373 void
376 374 distribute_rxm(Avo_DoJobMsg *dmake_job_msg)
377 375 {
378 376 /* Add all dynamic env vars to the dmake_job_msg. */
379 377 setvar_envvar(dmake_job_msg);
380 378
381 379 /*
382 380 * Copying dosys()...
383 381 * Stat .make.state to see if we'll need to reread it later
384 382 */
385 383 make_state->stat.time = file_no_time;
386 384 (void)exists(make_state);
387 385 make_state_before = make_state->stat.time;
388 386
389 387 // Wait for the first Acknowledge message from the rxm process
390 388 // before sending the first message.
391 389 if (!firstAcknowledgeReceived) {
392 390 firstAcknowledgeReceived++;
393 391 Avo_AcknowledgeMsg *msg = getAcknowledgeMsg();
394 392 if (msg) {
395 393 delete msg;
396 394 }
397 395 }
398 396
399 397 RWCollectable *doJobMsg = (RWCollectable *)dmake_job_msg;
400 398 sigset_t newset;
401 399 sigset_t oldset;
402 400
403 401 AVO_BLOCK_INTERUPTS;
404 402 int xdrResult = xdr(&xdrs_out, doJobMsg);
405 403
406 404 if (xdrResult) {
407 405 fflush(dmake_ofp);
408 406 AVO_UNBLOCK_INTERUPTS;
409 407 } else {
410 408 AVO_UNBLOCK_INTERUPTS;
411 409 fatal(catgets(catd, 1, 249, "Couldn't send the job request to rxm"));
412 410 }
413 411
414 412 delete dmake_job_msg;
415 413 }
416 414
417 415 // Queue for JobResult messages.
418 416 static RWSlistCollectablesQueue jobResultQueue;
419 417
420 418 // Queue for Acknowledge messages.
421 419 static RWSlistCollectablesQueue acknowledgeQueue;
422 420
423 421 // Read a message from the rxm process, and put it into a queue, by
424 422 // message type. Return the message type.
425 423
426 424 int
427 425 getRxmMessage(void)
428 426 {
429 427 RWCollectable *msg = (RWCollectable *)0;
430 428 int msgType = 0;
431 429 // sigset_t newset;
432 430 // sigset_t oldset;
433 431
434 432 // It seems unnecessarily to block interrupts here because
435 433 // any nonignored signal means exit for dmake in distributed mode.
436 434 // AVO_BLOCK_INTERUPTS;
437 435 int xdrResult = xdr(&xdrs_in, msg);
438 436 // AVO_UNBLOCK_INTERUPTS;
439 437
440 438 if (xdrResult) {
441 439 switch(msg->isA()) {
442 440 case __AVO_ACKNOWLEDGEMSG:
443 441 acknowledgeQueue.append(msg);
444 442 msgType = __AVO_ACKNOWLEDGEMSG;
445 443 break;
446 444 case __AVO_JOBRESULTMSG:
447 445 jobResultQueue.append(msg);
448 446 msgType = __AVO_JOBRESULTMSG;
449 447 break;
450 448 default:
451 449 warning(catgets(catd, 1, 291, "Unknown message on rxm input fd"));
452 450 msgType = 0;
453 451 break;
454 452 }
455 453 } else {
456 454 if (errno == EINTR) {
457 455 fputs(NOCATGETS("dmake: Internal error: xdr() has been interrupted by a signal.\n"), stderr);
458 456 }
459 457 fatal(catgets(catd, 1, 250, "Couldn't receive message from rxm"));
460 458 }
461 459
462 460 return msgType;
463 461 }
464 462
465 463 // Get a JobResult message from it's queue, and
466 464 // if the queue is empty, call the getRxmMessage() function until
467 465 // a JobResult message shows.
468 466
469 467 Avo_JobResultMsg *
470 468 getJobResultMsg(void)
471 469 {
472 470 RWCollectable *msg = 0;
473 471
474 472 if (!(msg = jobResultQueue.get())) {
475 473 while (getRxmMessage() != __AVO_JOBRESULTMSG);
476 474 msg = jobResultQueue.get();
477 475 }
478 476
479 477 return (Avo_JobResultMsg *)msg;
480 478 }
481 479
482 480 // Get an Acknowledge message from it's queue, and
483 481 // if the queue is empty, call the getRxmMessage() function until
484 482 // a Acknowledge message shows.
485 483
486 484 Avo_AcknowledgeMsg *
487 485 getAcknowledgeMsg(void)
488 486 {
489 487 RWCollectable *msg = 0;
490 488
491 489 if (!(msg = acknowledgeQueue.get())) {
492 490 while (getRxmMessage() != __AVO_ACKNOWLEDGEMSG);
493 491 msg = acknowledgeQueue.get();
494 492 }
495 493
496 494 return (Avo_AcknowledgeMsg *)msg;
497 495 }
498 496
499 497
500 498 /*
501 499 * Doname
502 500 * await_dist(Boolean waitflg)
503 501 *
504 502 * Waits for distributed children to exit and finishes their processing.
505 503 * Rxm will send a msg down the pipe when a child is done.
506 504 *
507 505 */
508 506 Doname
509 507 await_dist(Boolean waitflg)
510 508 {
511 509 Avo_JobResultMsg *dmake_result_msg;
512 510 int job_msg_id;
513 511 Doname result = build_ok;
514 512 int result_msg_cmd_status;
515 513 int result_msg_job_status;
516 514 Running rp;
517 515
518 516 while (!(dmake_result_msg = getJobResultMsg()));
519 517 job_msg_id = dmake_result_msg->getId();
520 518 result_msg_cmd_status = dmake_result_msg->getCmdStatus();
521 519 result_msg_job_status = dmake_result_msg->getJobStatus();
522 520
523 521 if (waitflg) {
524 522 result = (result_msg_cmd_status == 0) ? build_ok : build_failed;
525 523
526 524 #ifdef PRINT_EXIT_STATUS
527 525 if (result == build_ok) {
528 526 warning(NOCATGETS("I'm in await_dist(), waitflg is true, and result is build_ok."));
529 527 } else {
530 528 warning(NOCATGETS("I'm in await_dist(), waitflg is true, and result is build_failed."));
531 529 }
532 530 #endif
533 531
534 532 } else {
535 533 for (rp = running_list;
536 534 (rp != NULL) && (job_msg_id != rp->job_msg_id);
537 535 rp = rp->next) {
538 536 }
539 537 if (rp == NULL) {
540 538 fatal(catgets(catd, 1, 251, "Internal error: returned child job_msg_id not in running_list"));
541 539 } else {
542 540 /* XXX - This may not be correct! */
543 541 if (result_msg_job_status == RETURNED) {
544 542 rp->state = build_ok;
545 543 } else {
546 544 rp->state = (result_msg_cmd_status == 0) ? build_ok : build_failed;
547 545 }
548 546 result = rp->state;
549 547
550 548 #ifdef PRINT_EXIT_STATUS
551 549 if (result == build_ok) {
552 550 warning(NOCATGETS("I'm in await_dist(), waitflg is false, and result is build_ok."));
553 551 } else {
554 552 warning(NOCATGETS("I'm in await_dist(), waitflg is false, and result is build_failed."));
555 553 }
556 554 #endif
557 555
558 556 }
559 557 parallel_process_cnt--;
560 558 }
561 559 delete dmake_result_msg;
562 560 return result;
563 561 }
564 562
565 563 #endif
566 564
567 565
↓ open down ↓ |
253 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX