Print this page
make: unifdef for MAKETOOL and DISTRIBUTED (undefined)
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/make/bin/parallel.cc
+++ new/usr/src/cmd/make/bin/parallel.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 2005 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #ifdef TEAMWARE_MAKE_CMN
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
27 27
28 28 /*
29 29 * parallel.cc
30 30 *
31 31 * Deal with the parallel processing
32 32 */
33 33
34 34 /*
35 35 * Included files
36 36 */
37 -#ifdef DISTRIBUTED
38 -#include <avo/strings.h> /* AVO_STRDUP() */
39 -#include <dm/Avo_DoJobMsg.h>
40 -#include <dm/Avo_MToolJobResultMsg.h>
41 -#endif
42 37 #include <errno.h> /* errno */
43 38 #include <fcntl.h>
44 39 #include <mk/defs.h>
45 40 #include <mksh/dosys.h> /* redirect_io() */
46 41 #include <mksh/macro.h> /* expand_value() */
47 42 #include <mksh/misc.h> /* getmem() */
48 43 #include <sys/signal.h>
49 44 #include <sys/stat.h>
50 45 #include <sys/types.h>
51 46 #include <sys/utsname.h>
52 47 #include <sys/wait.h>
53 48 #include <unistd.h>
54 49 #include <netdb.h>
55 50
56 51
57 52
58 53 /*
59 54 * Defined macros
60 55 */
61 56 #define MAXRULES 100
62 57
63 58 /*
64 59 * This const should be in avo_dms/include/AvoDmakeCommand.h
65 60 */
66 61 const int local_host_mask = 0x20;
67 62
68 63
69 64 /*
70 65 * typedefs & structs
71 66 */
72 67
73 68
74 69 /*
75 70 * Static variables
76 71 */
77 72 #ifdef TEAMWARE_MAKE_CMN
78 73 static Boolean just_did_subtree = false;
79 74 static char local_host[MAXNAMELEN] = "";
80 75 static char user_name[MAXNAMELEN] = "";
81 76 #endif
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
82 77 static int pmake_max_jobs = 0;
83 78 static pid_t process_running = -1;
84 79 static Running *running_tail = &running_list;
85 80 static Name subtree_conflict;
86 81 static Name subtree_conflict2;
87 82
88 83
89 84 /*
90 85 * File table of contents
91 86 */
92 -#ifdef DISTRIBUTED
93 -static void append_dmake_cmd(Avo_DoJobMsg *dmake_job_msg, char *orig_cmd_line, int cmd_options);
94 -static void append_job_result_msg(Avo_MToolJobResultMsg *msg, char *outFn, char *errFn);
95 -static void send_job_result_msg(Running rp);
96 -#endif
97 87 static void delete_running_struct(Running rp);
98 88 static Boolean dependency_conflict(Name target);
99 89 static Doname distribute_process(char **commands, Property line);
100 90 static void doname_subtree(Name target, Boolean do_get, Boolean implicit);
101 91 static void dump_out_file(char *filename, Boolean err);
102 92 static void finish_doname(Running rp);
103 93 static void maybe_reread_make_state(void);
104 94 static void process_next(void);
105 95 static void reset_conditionals(int cnt, Name *targets, Property *locals);
106 96 static pid_t run_rule_commands(char *host, char **commands);
107 97 static Property *set_conditionals(int cnt, Name *targets);
108 98 static void store_conditionals(Running rp);
109 99
110 100
111 101 /*
112 102 * execute_parallel(line, waitflg)
113 103 *
114 104 * DMake 2.x:
115 105 * parallel mode: spawns a parallel process to execute the command group.
116 106 * distributed mode: sends the command group down the pipe to rxm.
117 107 *
118 108 * Return value:
119 109 * The result of the execution
120 110 *
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
121 111 * Parameters:
122 112 * line The command group to execute
123 113 */
124 114 Doname
125 115 execute_parallel(Property line, Boolean waitflg, Boolean local)
126 116 {
127 117 int argcnt;
128 118 int cmd_options = 0;
129 119 char *commands[MAXRULES + 5];
130 120 char *cp;
131 -#ifdef DISTRIBUTED
132 - Avo_DoJobMsg *dmake_job_msg = NULL;
133 -#endif
134 121 Name dmake_name;
135 122 Name dmake_value;
136 123 int ignore;
137 124 Name make_machines_name;
138 125 char **p;
139 126 Property prop;
140 127 Doname result = build_ok;
141 128 Cmd_line rule;
142 129 Boolean silent_flag;
143 130 Name target = line->body.line.target;
144 131 Boolean wrote_state_file = false;
145 132
146 133 if ((pmake_max_jobs == 0) &&
147 134 (dmake_mode_type == parallel_mode)) {
148 135 if (local_host[0] == '\0') {
149 136 (void) gethostname(local_host, MAXNAMELEN);
150 137 }
151 138 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS"));
152 139 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
153 140 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
154 141 ((dmake_value = prop->body.macro.value) != NULL)) {
155 142 pmake_max_jobs = atoi(dmake_value->string_mb);
156 143 if (pmake_max_jobs <= 0) {
157 144 warning(catgets(catd, 1, 308, "DMAKE_MAX_JOBS cannot be less than or equal to zero."));
158 145 warning(catgets(catd, 1, 309, "setting DMAKE_MAX_JOBS to %d."), PMAKE_DEF_MAX_JOBS);
159 146 pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
160 147 }
161 148 } else {
162 149 /*
163 150 * For backwards compatibility w/ PMake 1.x, when
164 151 * DMake 2.x is being run in parallel mode, DMake
165 152 * should parse the PMake startup file
166 153 * $(HOME)/.make.machines to get the pmake_max_jobs.
167 154 */
168 155 MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE"));
169 156 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
170 157 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
171 158 ((dmake_value = prop->body.macro.value) != NULL)) {
172 159 make_machines_name = dmake_value;
173 160 } else {
174 161 make_machines_name = NULL;
175 162 }
176 163 if ((pmake_max_jobs = read_make_machines(make_machines_name)) <= 0) {
177 164 pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
178 165 }
179 166 }
180 -#ifdef DISTRIBUTED
181 - if (send_mtool_msgs) {
182 - send_rsrc_info_msg(pmake_max_jobs, local_host, user_name);
183 - }
184 -#endif
185 167 }
186 168
187 169 if ((dmake_mode_type == serial_mode) ||
188 170 ((dmake_mode_type == parallel_mode) && (waitflg))) {
189 171 return (execute_serial(line));
190 172 }
191 173
192 -#ifdef DISTRIBUTED
193 - if (dmake_mode_type == distributed_mode) {
194 - if(local) {
195 -// return (execute_serial(line));
196 - waitflg = true;
197 - }
198 - dmake_job_msg = new Avo_DoJobMsg();
199 - dmake_job_msg->setJobId(++job_msg_id);
200 - dmake_job_msg->setTarget(target->string_mb);
201 - dmake_job_msg->setImmediateOutput(0);
202 - called_make = false;
203 - } else
204 -#endif
205 174 {
206 175 p = commands;
207 176 }
208 177
209 178 argcnt = 0;
210 179 for (rule = line->body.line.command_used;
211 180 rule != NULL;
212 181 rule = rule->next) {
213 182 if (posix && (touch || quest) && !rule->always_exec) {
214 183 continue;
215 184 }
216 185 if (vpath_defined) {
217 186 rule->command_line =
218 187 vpath_translation(rule->command_line);
219 188 }
220 189 if (dmake_mode_type == distributed_mode) {
221 190 cmd_options = 0;
222 191 if(local) {
223 192 cmd_options |= local_host_mask;
224 193 }
225 194 } else {
226 195 silent_flag = false;
227 196 ignore = 0;
228 197 }
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
229 198 if (rule->command_line->hash.length > 0) {
230 199 if (++argcnt == MAXRULES) {
231 200 if (dmake_mode_type == distributed_mode) {
232 201 /* XXX - tell rxm to execute on local host. */
233 202 /* I WAS HERE!!! */
234 203 } else {
235 204 /* Too many rules, run serially instead. */
236 205 return build_serial;
237 206 }
238 207 }
239 -#ifdef DISTRIBUTED
240 - if (dmake_mode_type == distributed_mode) {
241 - /*
242 - * XXX - set assign_mask to tell rxm
243 - * to do the following.
244 - */
245 -/* From execute_serial():
246 - if (rule->assign) {
247 - result = build_ok;
248 - do_assign(rule->command_line, target);
249 - */
250 - if (0) {
251 - } else if (report_dependencies_level == 0) {
252 - if (rule->ignore_error) {
253 - cmd_options |= ignore_mask;
254 - }
255 - if (rule->silent) {
256 - cmd_options |= silent_mask;
257 - }
258 - if (rule->command_line->meta) {
259 - cmd_options |= meta_mask;
260 - }
261 - if (rule->make_refd) {
262 - cmd_options |= make_refd_mask;
263 - }
264 - if (do_not_exec_rule) {
265 - cmd_options |= do_not_exec_mask;
266 - }
267 - append_dmake_cmd(dmake_job_msg,
268 - rule->command_line->string_mb,
269 - cmd_options);
270 - /* Copying dosys()... */
271 - if (rule->make_refd) {
272 - if (waitflg) {
273 - dmake_job_msg->setImmediateOutput(1);
274 - }
275 - called_make = true;
276 - if (command_changed &&
277 - !wrote_state_file) {
278 - write_state_file(0, false);
279 - wrote_state_file = true;
280 - }
281 - }
282 - }
283 - } else
284 -#endif
285 208 {
286 209 if (rule->silent && !silent) {
287 210 silent_flag = true;
288 211 }
289 212 if (rule->ignore_error) {
290 213 ignore++;
291 214 }
292 215 /* XXX - need to add support for + prefix */
293 216 if (silent_flag || ignore) {
294 217 *p = getmem((silent_flag ? 1 : 0) +
295 218 ignore +
296 219 (strlen(rule->
297 220 command_line->
298 221 string_mb)) +
299 222 1);
300 223 cp = *p++;
301 224 if (silent_flag) {
302 225 *cp++ = (int) at_char;
303 226 }
304 227 if (ignore) {
305 228 *cp++ = (int) hyphen_char;
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
306 229 }
307 230 (void) strcpy(cp, rule->command_line->string_mb);
308 231 } else {
309 232 *p++ = rule->command_line->string_mb;
310 233 }
311 234 }
312 235 }
313 236 }
314 237 if ((argcnt == 0) ||
315 238 (report_dependencies_level > 0)) {
316 -#ifdef DISTRIBUTED
317 - if (dmake_job_msg) {
318 - delete dmake_job_msg;
319 - }
320 -#endif
321 239 return build_ok;
322 240 }
323 -#ifdef DISTRIBUTED
324 - if (dmake_mode_type == distributed_mode) {
325 - // Send a DoJob message to the rxm process.
326 - distribute_rxm(dmake_job_msg);
327 -
328 - // Wait for an acknowledgement.
329 - Avo_AcknowledgeMsg *ackMsg = getAcknowledgeMsg();
330 - if (ackMsg) {
331 - delete ackMsg;
332 - }
333 -
334 - if (waitflg) {
335 - // Wait for, and process a job result.
336 - result = await_dist(waitflg);
337 - if (called_make) {
338 - maybe_reread_make_state();
339 - }
340 - check_state(temp_file_name);
341 - if (result == build_failed) {
342 - if (!continue_after_error) {
343 -
344 -#ifdef PRINT_EXIT_STATUS
345 - warning(NOCATGETS("I'm in execute_parallel. await_dist() returned build_failed"));
346 -#endif
347 -
348 - fatal(catgets(catd, 1, 252, "Command failed for target `%s'"),
349 - target->string_mb);
350 - }
351 - /*
352 - * Make sure a failing command is not
353 - * saved in .make.state.
354 - */
355 - line->body.line.command_used = NULL;
356 - }
357 - if (temp_file_name != NULL) {
358 - free_name(temp_file_name);
359 - }
360 - temp_file_name = NULL;
361 - Property spro = get_prop(sunpro_dependencies->prop, macro_prop);
362 - if(spro != NULL) {
363 - Name val = spro->body.macro.value;
364 - if(val != NULL) {
365 - free_name(val);
366 - spro->body.macro.value = NULL;
367 - }
368 - }
369 - spro = get_prop(sunpro_dependencies->prop, env_mem_prop);
370 - if(spro) {
371 - char *val = spro->body.env_mem.value;
372 - if(val != NULL) {
373 - retmem_mb(val);
374 - spro->body.env_mem.value = NULL;
375 - }
376 - }
377 - return result;
378 - } else {
379 - parallel_process_cnt++;
380 - return build_running;
381 - }
382 - } else
383 -#endif
384 241 {
385 242 *p = NULL;
386 243
387 244 Doname res = distribute_process(commands, line);
388 245 if (res == build_running) {
389 246 parallel_process_cnt++;
390 247 }
391 248
392 249 /*
393 250 * Return only those memory that were specially allocated
394 251 * for part of commands.
395 252 */
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
396 253 for (int i = 0; commands[i] != NULL; i++) {
397 254 if ((commands[i][0] == (int) at_char) ||
398 255 (commands[i][0] == (int) hyphen_char)) {
399 256 retmem_mb(commands[i]);
400 257 }
401 258 }
402 259 return res;
403 260 }
404 261 }
405 262
406 -#ifdef DISTRIBUTED
407 -/*
408 - * append_dmake_cmd()
409 - *
410 - * Replaces all escaped newline's (\<cr>)
411 - * in the original command line with space's,
412 - * then append the new command line to the DoJobMsg object.
413 - */
414 -static void
415 -append_dmake_cmd(Avo_DoJobMsg *dmake_job_msg,
416 - char *orig_cmd_line,
417 - int cmd_options)
418 -{
419 -/*
420 - Avo_DmakeCommand *tmp_dmake_command;
421 -
422 - tmp_dmake_command = new Avo_DmakeCommand(orig_cmd_line, cmd_options);
423 - dmake_job_msg->appendCmd(tmp_dmake_command);
424 - delete tmp_dmake_command;
425 - */
426 - dmake_job_msg->appendCmd(new Avo_DmakeCommand(orig_cmd_line, cmd_options));
427 -}
428 -#endif
429 263
430 264 #ifdef TEAMWARE_MAKE_CMN
431 265 #define MAXJOBS_ADJUST_RFE4694000
432 266
433 267 #ifdef MAXJOBS_ADJUST_RFE4694000
434 268
435 269 #include <unistd.h> /* sysconf(_SC_NPROCESSORS_ONLN) */
436 270 #include <sys/ipc.h> /* ftok() */
437 271 #include <sys/shm.h> /* shmget(), shmat(), shmdt(), shmctl() */
438 272 #include <semaphore.h> /* sem_init(), sem_trywait(), sem_post(), sem_destroy() */
439 273 #include <sys/loadavg.h> /* getloadavg() */
440 274
441 275 /*
442 276 * adjust_pmake_max_jobs (int pmake_max_jobs)
443 277 *
444 278 * Parameters:
445 279 * pmake_max_jobs - max jobs limit set by user
446 280 *
447 281 * External functions used:
448 282 * sysconf()
449 283 * getloadavg()
450 284 */
451 285 static int
452 286 adjust_pmake_max_jobs (int pmake_max_jobs)
453 287 {
454 288 static int ncpu = 0;
455 289 double loadavg[3];
456 290 int adjustment;
457 291 int adjusted_max_jobs;
458 292
459 293 if (ncpu <= 0) {
460 294 if ((ncpu = sysconf(_SC_NPROCESSORS_ONLN)) <= 0) {
461 295 ncpu = 1;
462 296 }
463 297 }
464 298 if (getloadavg(loadavg, 3) != 3) return(pmake_max_jobs);
465 299 adjustment = ((int)loadavg[LOADAVG_1MIN]);
466 300 if (adjustment < 2) return(pmake_max_jobs);
467 301 if (ncpu > 1) {
468 302 adjustment = adjustment / ncpu;
469 303 }
470 304 adjusted_max_jobs = pmake_max_jobs - adjustment;
471 305 if (adjusted_max_jobs < 1) adjusted_max_jobs = 1;
472 306 return(adjusted_max_jobs);
473 307 }
474 308
475 309 /*
476 310 * M2 adjust mode data and functions
477 311 *
478 312 * m2_init() - initializes M2 shared semaphore
479 313 * m2_acquire_job() - decrements M2 semaphore counter
480 314 * m2_release_job() - increments M2 semaphore counter
481 315 * m2_fini() - destroys M2 semaphore and shared memory*
482 316 *
483 317 * Environment variables:
484 318 * __DMAKE_M2_FILE__
485 319 *
486 320 * External functions:
487 321 * ftok(), shmget(), shmat(), shmdt(), shmctl()
488 322 * sem_init(), sem_trywait(), sem_post(), sem_destroy()
489 323 * creat(), close(), unlink()
490 324 * getenv(), putenv()
491 325 *
492 326 * Static variables:
493 327 * m2_file - tmp file name to create ipc key for shared memory
494 328 * m2_shm_id - shared memory id
495 329 * m2_shm_sem - shared memory semaphore
496 330 */
497 331
498 332 static char m2_file[MAXPATHLEN];
499 333 static int m2_shm_id = -1;
500 334 static sem_t* m2_shm_sem = 0;
501 335
502 336 static int
503 337 m2_init() {
504 338 char *var;
505 339 key_t key;
506 340
507 341 if ((var = getenv(NOCATGETS("__DMAKE_M2_FILE__"))) == 0) {
508 342 /* compose tmp file name */
509 343 sprintf(m2_file, NOCATGETS("%s/dmake.m2.%d.XXXXXX"), tmpdir, getpid());
510 344
511 345 /* create tmp file */
512 346 int fd = mkstemp(m2_file);
513 347 if (fd < 0) {
514 348 return -1;
515 349 } else {
516 350 close(fd);
517 351 }
518 352 } else {
519 353 /* using existing semaphore */
520 354 strcpy(m2_file, var);
521 355 }
522 356
523 357 /* combine IPC key */
524 358 if ((key = ftok(m2_file, 38)) == (key_t) -1) {
525 359 return -1;
526 360 }
527 361
528 362 /* create shared memory */
529 363 if ((m2_shm_id = shmget(key, sizeof(*m2_shm_sem), 0666 | (var ? 0 : IPC_CREAT|IPC_EXCL))) == -1) {
530 364 return -1;
531 365 }
532 366
533 367 /* attach shared memory */
534 368 if ((m2_shm_sem = (sem_t*) shmat(m2_shm_id, 0, 0666)) == (sem_t*)-1) {
535 369 return -1;
536 370 }
537 371
538 372 /* root process */
539 373 if (var == 0) {
540 374 /* initialize semaphore */
541 375 if (sem_init(m2_shm_sem, 1, pmake_max_jobs)) {
542 376 return -1;
543 377 }
544 378
545 379 /* alloc memory for env variable */
546 380 if ((var = (char*) malloc(MAXPATHLEN)) == 0) {
547 381 return -1;
548 382 }
549 383
550 384 /* put key to env */
551 385 sprintf(var, NOCATGETS("__DMAKE_M2_FILE__=%s"), m2_file);
552 386 if (putenv(var)) {
553 387 return -1;
554 388 }
555 389 }
556 390 return 0;
557 391 }
558 392
559 393 static void
560 394 m2_fini() {
561 395 if (m2_shm_id >= 0) {
562 396 struct shmid_ds stat;
563 397
564 398 /* determine the number of attached processes */
565 399 if (shmctl(m2_shm_id, IPC_STAT, &stat) == 0) {
566 400 if (stat.shm_nattch <= 1) {
567 401 /* destroy semaphore */
568 402 if (m2_shm_sem != 0) {
569 403 (void) sem_destroy(m2_shm_sem);
570 404 }
571 405
572 406 /* destroy shared memory */
573 407 (void) shmctl(m2_shm_id, IPC_RMID, &stat);
574 408
575 409 /* remove tmp file created for the key */
576 410 (void) unlink(m2_file);
577 411 } else {
578 412 /* detach shared memory */
579 413 if (m2_shm_sem != 0) {
580 414 (void) shmdt((char*) m2_shm_sem);
581 415 }
582 416 }
583 417 }
584 418
585 419 m2_shm_id = -1;
586 420 m2_shm_sem = 0;
587 421 }
588 422 }
589 423
590 424 static int
591 425 m2_acquire_job() {
592 426 if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) {
593 427 if (sem_trywait(m2_shm_sem) == 0) {
594 428 return 1;
595 429 }
596 430 if (errno == EAGAIN) {
597 431 return 0;
598 432 }
599 433 }
600 434 return -1;
601 435 }
602 436
603 437 static int
604 438 m2_release_job() {
605 439 if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) {
606 440 if (sem_post(m2_shm_sem) == 0) {
607 441 return 0;
608 442 }
609 443 }
610 444 return -1;
611 445 }
612 446
613 447 /*
614 448 * job adjust mode
615 449 *
616 450 * Possible values:
617 451 * ADJUST_M1 - adjustment by system load (default)
618 452 * ADJUST_M2 - fixed limit of jobs for the group of nested dmakes
619 453 * ADJUST_NONE - no adjustment - fixed limit of jobs for the current dmake
620 454 */
621 455 static enum {
622 456 ADJUST_UNKNOWN,
623 457 ADJUST_M1,
624 458 ADJUST_M2,
625 459 ADJUST_NONE
626 460 } job_adjust_mode = ADJUST_UNKNOWN;
627 461
628 462 /*
629 463 * void job_adjust_fini()
630 464 *
631 465 * Description:
632 466 * Cleans up job adjust data.
633 467 *
634 468 * Static variables:
635 469 * job_adjust_mode Current job adjust mode
636 470 */
637 471 void
638 472 job_adjust_fini() {
639 473 if (job_adjust_mode == ADJUST_M2) {
640 474 m2_fini();
641 475 }
642 476 }
643 477
644 478 /*
645 479 * void job_adjust_error()
646 480 *
647 481 * Description:
648 482 * Prints warning message, cleans up job adjust data, and disables job adjustment
649 483 *
650 484 * Environment:
651 485 * DMAKE_ADJUST_MAX_JOBS
652 486 *
653 487 * External functions:
654 488 * putenv()
655 489 *
656 490 * Static variables:
657 491 * job_adjust_mode Current job adjust mode
658 492 */
659 493 static void
660 494 job_adjust_error() {
661 495 if (job_adjust_mode != ADJUST_NONE) {
662 496 /* cleanup internals */
663 497 job_adjust_fini();
664 498
665 499 /* warning message for the user */
666 500 warning(catgets(catd, 1, 339, "Encountered max jobs auto adjustment error - disabling auto adjustment."));
667 501
668 502 /* switch off job adjustment for the children */
669 503 putenv(strdup(NOCATGETS("DMAKE_ADJUST_MAX_JOBS=NO")));
670 504
671 505 /* and for this dmake */
672 506 job_adjust_mode = ADJUST_NONE;
673 507 }
674 508 }
675 509
676 510 /*
677 511 * void job_adjust_init()
678 512 *
679 513 * Description:
680 514 * Parses DMAKE_ADJUST_MAX_JOBS env variable
681 515 * and performs appropriate initializations.
682 516 *
683 517 * Environment:
684 518 * DMAKE_ADJUST_MAX_JOBS
685 519 * DMAKE_ADJUST_MAX_JOBS == "NO" - no adjustment
686 520 * DMAKE_ADJUST_MAX_JOBS == "M2" - M2 adjust mode
687 521 * other - M1 adjust mode
688 522 *
689 523 * External functions:
690 524 * getenv()
691 525 *
692 526 * Static variables:
693 527 * job_adjust_mode Current job adjust mode
694 528 */
695 529 static void
696 530 job_adjust_init() {
697 531 if (job_adjust_mode == ADJUST_UNKNOWN) {
698 532 /* default mode */
699 533 job_adjust_mode = ADJUST_M1;
700 534
701 535 /* determine adjust mode */
702 536 if (char *var = getenv(NOCATGETS("DMAKE_ADJUST_MAX_JOBS"))) {
703 537 if (strcasecmp(var, NOCATGETS("NO")) == 0) {
704 538 job_adjust_mode = ADJUST_NONE;
705 539 } else if (strcasecmp(var, NOCATGETS("M2")) == 0) {
706 540 job_adjust_mode = ADJUST_M2;
707 541 }
708 542 }
709 543
710 544 /* M2 specific initialization */
711 545 if (job_adjust_mode == ADJUST_M2) {
712 546 if (m2_init()) {
713 547 job_adjust_error();
714 548 }
715 549 }
716 550 }
717 551 }
718 552
719 553 #endif /* MAXJOBS_ADJUST_RFE4694000 */
720 554 #endif /* TEAMWARE_MAKE_CMN */
721 555
722 556 /*
723 557 * distribute_process(char **commands, Property line)
724 558 *
725 559 * Parameters:
726 560 * commands argv vector of commands to execute
727 561 *
728 562 * Return value:
729 563 * The result of the execution
730 564 *
731 565 * Static variables used:
732 566 * process_running Set to the pid of the process set running
733 567 * #if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000)
734 568 * job_adjust_mode Current job adjust mode
735 569 * #endif
736 570 */
737 571 static Doname
738 572 distribute_process(char **commands, Property line)
739 573 {
740 574 static unsigned file_number = 0;
741 575 wchar_t string[MAXPATHLEN];
742 576 char mbstring[MAXPATHLEN];
743 577 int filed;
744 578 int res;
745 579 int tmp_index;
746 580 char *tmp_index_str_ptr;
747 581
748 582 #if !defined (TEAMWARE_MAKE_CMN) || !defined (MAXJOBS_ADJUST_RFE4694000)
749 583 while (parallel_process_cnt >= pmake_max_jobs) {
750 584 await_parallel(false);
751 585 finish_children(true);
752 586 }
753 587 #else /* TEAMWARE_MAKE_CMN && MAXJOBS_ADJUST_RFE4694000 */
754 588 /* initialize adjust mode, if not initialized */
755 589 if (job_adjust_mode == ADJUST_UNKNOWN) {
756 590 job_adjust_init();
757 591 }
758 592
759 593 /* actions depend on adjust mode */
760 594 switch (job_adjust_mode) {
761 595 case ADJUST_M1:
762 596 while (parallel_process_cnt >= adjust_pmake_max_jobs (pmake_max_jobs)) {
763 597 await_parallel(false);
764 598 finish_children(true);
765 599 }
766 600 break;
767 601 case ADJUST_M2:
768 602 if ((res = m2_acquire_job()) == 0) {
769 603 if (parallel_process_cnt > 0) {
770 604 await_parallel(false);
771 605 finish_children(true);
772 606
773 607 if ((res = m2_acquire_job()) == 0) {
774 608 return build_serial;
775 609 }
776 610 } else {
777 611 return build_serial;
778 612 }
779 613 }
780 614 if (res < 0) {
781 615 /* job adjustment error */
782 616 job_adjust_error();
783 617
784 618 /* no adjustment */
785 619 while (parallel_process_cnt >= pmake_max_jobs) {
786 620 await_parallel(false);
787 621 finish_children(true);
↓ open down ↓ |
349 lines elided |
↑ open up ↑ |
788 622 }
789 623 }
790 624 break;
791 625 default:
792 626 while (parallel_process_cnt >= pmake_max_jobs) {
793 627 await_parallel(false);
794 628 finish_children(true);
795 629 }
796 630 }
797 631 #endif /* TEAMWARE_MAKE_CMN && MAXJOBS_ADJUST_RFE4694000 */
798 -#ifdef DISTRIBUTED
799 - if (send_mtool_msgs) {
800 - send_job_start_msg(line);
801 - }
802 -#endif
803 -#ifdef DISTRIBUTED
804 - setvar_envvar((Avo_DoJobMsg *)NULL);
805 -#else
806 632 setvar_envvar();
807 -#endif
808 633 /*
809 634 * Tell the user what DMake is doing.
810 635 */
811 636 if (!silent && output_mode != txt2_mode) {
812 637 /*
813 638 * Print local_host --> x job(s).
814 639 */
815 640 (void) fprintf(stdout,
816 641 catgets(catd, 1, 325, "%s --> %d %s\n"),
817 642 local_host,
818 643 parallel_process_cnt + 1,
819 644 (parallel_process_cnt == 0) ? catgets(catd, 1, 124, "job") : catgets(catd, 1, 125, "jobs"));
820 645
821 646 /* Print command line(s). */
822 647 tmp_index = 0;
823 648 while (commands[tmp_index] != NULL) {
824 649 /* No @ char. */
825 650 /* XXX - need to add [2] when + prefix is added */
826 651 if ((commands[tmp_index][0] != (int) at_char) &&
827 652 (commands[tmp_index][1] != (int) at_char)) {
828 653 tmp_index_str_ptr = commands[tmp_index];
829 654 if (*tmp_index_str_ptr == (int) hyphen_char) {
830 655 tmp_index_str_ptr++;
831 656 }
832 657 (void) fprintf(stdout, "%s\n", tmp_index_str_ptr);
833 658 }
834 659 tmp_index++;
835 660 }
836 661 (void) fflush(stdout);
837 662 }
838 663
839 664 (void) sprintf(mbstring,
840 665 NOCATGETS("%s/dmake.stdout.%d.%d.XXXXXX"),
841 666 tmpdir,
842 667 getpid(),
843 668 file_number++);
844 669
845 670 mktemp(mbstring);
846 671
847 672 stdout_file = strdup(mbstring);
848 673 stderr_file = NULL;
849 674 #if defined (TEAMWARE_MAKE_CMN)
850 675 if (!out_err_same) {
851 676 (void) sprintf(mbstring,
852 677 NOCATGETS("%s/dmake.stderr.%d.%d.XXXXXX"),
853 678 tmpdir,
854 679 getpid(),
855 680 file_number++);
856 681
857 682 mktemp(mbstring);
858 683
859 684 stderr_file = strdup(mbstring);
860 685 }
861 686 #endif
862 687
863 688 process_running = run_rule_commands(local_host, commands);
864 689
865 690 return build_running;
866 691 }
867 692
868 693 /*
869 694 * doname_parallel(target, do_get, implicit)
870 695 *
871 696 * Processes the given target and finishes up any parallel
872 697 * processes left running.
873 698 *
874 699 * Return value:
875 700 * Result of target build
876 701 *
877 702 * Parameters:
878 703 * target Target to build
879 704 * do_get True if sccs get to be done
880 705 * implicit True if this is an implicit target
881 706 */
882 707 Doname
883 708 doname_parallel(Name target, Boolean do_get, Boolean implicit)
884 709 {
885 710 Doname result;
886 711
887 712 result = doname_check(target, do_get, implicit, false);
888 713 if (result == build_ok || result == build_failed) {
889 714 return result;
890 715 }
891 716 finish_running();
892 717 return (Doname) target->state;
893 718 }
894 719
895 720 /*
896 721 * doname_subtree(target, do_get, implicit)
897 722 *
898 723 * Completely computes an object and its dependents for a
899 724 * serial subtree build.
900 725 *
901 726 * Parameters:
902 727 * target Target to build
903 728 * do_get True if sccs get to be done
904 729 * implicit True if this is an implicit target
905 730 *
906 731 * Static variables used:
907 732 * running_tail Tail of the list of running processes
908 733 *
909 734 * Global variables used:
910 735 * running_list The list of running processes
911 736 */
912 737 static void
913 738 doname_subtree(Name target, Boolean do_get, Boolean implicit)
914 739 {
915 740 Running save_running_list;
916 741 Running *save_running_tail;
917 742
918 743 save_running_list = running_list;
919 744 save_running_tail = running_tail;
920 745 running_list = NULL;
921 746 running_tail = &running_list;
922 747 target->state = build_subtree;
923 748 target->checking_subtree = true;
924 749 while(doname_check(target, do_get, implicit, false) == build_running) {
925 750 target->checking_subtree = false;
926 751 finish_running();
927 752 target->state = build_subtree;
928 753 }
929 754 target->checking_subtree = false;
930 755 running_list = save_running_list;
931 756 running_tail = save_running_tail;
932 757 }
933 758
934 759 /*
935 760 * finish_running()
936 761 *
937 762 * Keeps processing until the running_list is emptied out.
↓ open down ↓ |
120 lines elided |
↑ open up ↑ |
938 763 *
939 764 * Parameters:
940 765 *
941 766 * Global variables used:
942 767 * running_list The list of running processes
943 768 */
944 769 void
945 770 finish_running(void)
946 771 {
947 772 while (running_list != NULL) {
948 -#ifdef DISTRIBUTED
949 - if (dmake_mode_type == distributed_mode) {
950 - if ((just_did_subtree) ||
951 - (parallel_process_cnt == 0)) {
952 - just_did_subtree = false;
953 - } else {
954 - (void) await_dist(false);
955 - finish_children(true);
956 - }
957 - } else
958 -#endif
959 773 {
960 774 await_parallel(false);
961 775 finish_children(true);
962 776 }
963 777 if (running_list != NULL) {
964 778 process_next();
965 779 }
966 780 }
967 781 }
968 782
969 783 /*
970 784 * process_next()
971 785 *
972 786 * Searches the running list for any targets which can start processing.
973 787 * This can be a pending target, a serial target, or a subtree target.
974 788 *
975 789 * Parameters:
976 790 *
977 791 * Static variables used:
978 792 * running_tail The end of the list of running procs
979 793 * subtree_conflict A target which conflicts with a subtree
980 794 * subtree_conflict2 The other target which conflicts
981 795 *
982 796 * Global variables used:
983 797 * commands_done True if commands executed
984 798 * debug_level Controls debug output
985 799 * parallel_process_cnt Number of parallel process running
986 800 * recursion_level Indentation for debug output
987 801 * running_list List of running processes
988 802 */
989 803 static void
990 804 process_next(void)
991 805 {
992 806 Running rp;
993 807 Running *rp_prev;
994 808 Property line;
995 809 Chain target_group;
996 810 Dependency dep;
997 811 Boolean quiescent = true;
998 812 Running *subtree_target;
999 813 Boolean saved_commands_done;
1000 814 Property *conditionals;
1001 815
1002 816 subtree_target = NULL;
1003 817 subtree_conflict = NULL;
1004 818 subtree_conflict2 = NULL;
1005 819 /*
1006 820 * If nothing currently running, build a serial target, if any.
1007 821 */
1008 822 start_loop_1:
1009 823 for (rp_prev = &running_list, rp = running_list;
1010 824 rp != NULL && parallel_process_cnt == 0;
1011 825 rp = rp->next) {
1012 826 if (rp->state == build_serial) {
1013 827 *rp_prev = rp->next;
1014 828 if (rp->next == NULL) {
1015 829 running_tail = rp_prev;
1016 830 }
1017 831 recursion_level = rp->recursion_level;
1018 832 rp->target->state = build_pending;
1019 833 (void) doname_check(rp->target,
1020 834 rp->do_get,
1021 835 rp->implicit,
1022 836 false);
1023 837 quiescent = false;
1024 838 delete_running_struct(rp);
1025 839 goto start_loop_1;
1026 840 } else {
1027 841 rp_prev = &rp->next;
1028 842 }
1029 843 }
1030 844 /*
1031 845 * Find a target to build. The target must be pending, have all
1032 846 * its dependencies built, and not be in a target group with a target
1033 847 * currently building.
1034 848 */
1035 849 start_loop_2:
1036 850 for (rp_prev = &running_list, rp = running_list;
1037 851 rp != NULL;
1038 852 rp = rp->next) {
1039 853 if (!(rp->state == build_pending ||
1040 854 rp->state == build_subtree)) {
1041 855 quiescent = false;
1042 856 rp_prev = &rp->next;
1043 857 } else if (rp->state == build_pending) {
1044 858 line = get_prop(rp->target->prop, line_prop);
1045 859 for (dep = line->body.line.dependencies;
1046 860 dep != NULL;
1047 861 dep = dep->next) {
1048 862 if (dep->name->state == build_running ||
1049 863 dep->name->state == build_pending ||
1050 864 dep->name->state == build_serial) {
1051 865 break;
1052 866 }
1053 867 }
1054 868 if (dep == NULL) {
1055 869 for (target_group = line->body.line.target_group;
1056 870 target_group != NULL;
1057 871 target_group = target_group->next) {
1058 872 if (is_running(target_group->name)) {
1059 873 break;
1060 874 }
1061 875 }
1062 876 if (target_group == NULL) {
1063 877 *rp_prev = rp->next;
1064 878 if (rp->next == NULL) {
1065 879 running_tail = rp_prev;
1066 880 }
1067 881 recursion_level = rp->recursion_level;
1068 882 rp->target->state = rp->redo ?
1069 883 build_dont_know : build_pending;
1070 884 saved_commands_done = commands_done;
1071 885 conditionals =
1072 886 set_conditionals
1073 887 (rp->conditional_cnt,
1074 888 rp->conditional_targets);
1075 889 rp->target->dont_activate_cond_values = true;
1076 890 if ((doname_check(rp->target,
1077 891 rp->do_get,
1078 892 rp->implicit,
1079 893 rp->target->has_target_prop ? true : false) !=
1080 894 build_running) &&
1081 895 !commands_done) {
1082 896 commands_done =
1083 897 saved_commands_done;
1084 898 }
1085 899 rp->target->dont_activate_cond_values = false;
1086 900 reset_conditionals
1087 901 (rp->conditional_cnt,
1088 902 rp->conditional_targets,
1089 903 conditionals);
1090 904 quiescent = false;
1091 905 delete_running_struct(rp);
1092 906 goto start_loop_2;
1093 907 } else {
1094 908 rp_prev = &rp->next;
1095 909 }
1096 910 } else {
1097 911 rp_prev = &rp->next;
1098 912 }
1099 913 } else {
1100 914 rp_prev = &rp->next;
1101 915 }
1102 916 }
1103 917 /*
1104 918 * If nothing has been found to build and there exists a subtree
1105 919 * target with no dependency conflicts, build it.
1106 920 */
1107 921 if (quiescent) {
1108 922 start_loop_3:
1109 923 for (rp_prev = &running_list, rp = running_list;
1110 924 rp != NULL;
1111 925 rp = rp->next) {
↓ open down ↓ |
143 lines elided |
↑ open up ↑ |
1112 926 if (rp->state == build_subtree) {
1113 927 if (!dependency_conflict(rp->target)) {
1114 928 *rp_prev = rp->next;
1115 929 if (rp->next == NULL) {
1116 930 running_tail = rp_prev;
1117 931 }
1118 932 recursion_level = rp->recursion_level;
1119 933 doname_subtree(rp->target,
1120 934 rp->do_get,
1121 935 rp->implicit);
1122 -#ifdef DISTRIBUTED
1123 - just_did_subtree = true;
1124 -#endif
1125 936 quiescent = false;
1126 937 delete_running_struct(rp);
1127 938 goto start_loop_3;
1128 939 } else {
1129 940 subtree_target = rp_prev;
1130 941 rp_prev = &rp->next;
1131 942 }
1132 943 } else {
1133 944 rp_prev = &rp->next;
1134 945 }
1135 946 }
1136 947 }
1137 948 /*
1138 949 * If still nothing found to build, we either have a deadlock
1139 950 * or a subtree with a dependency conflict with something waiting
1140 951 * to build.
1141 952 */
1142 953 if (quiescent) {
1143 954 if (subtree_target == NULL) {
1144 955 fatal(catgets(catd, 1, 126, "Internal error: deadlock detected in process_next"));
1145 956 } else {
1146 957 rp = *subtree_target;
1147 958 if (debug_level > 0) {
1148 959 warning(catgets(catd, 1, 127, "Conditional macro conflict encountered for %s between %s and %s"),
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
1149 960 subtree_conflict2->string_mb,
1150 961 rp->target->string_mb,
1151 962 subtree_conflict->string_mb);
1152 963 }
1153 964 *subtree_target = (*subtree_target)->next;
1154 965 if (rp->next == NULL) {
1155 966 running_tail = subtree_target;
1156 967 }
1157 968 recursion_level = rp->recursion_level;
1158 969 doname_subtree(rp->target, rp->do_get, rp->implicit);
1159 -#ifdef DISTRIBUTED
1160 - just_did_subtree = true;
1161 -#endif
1162 970 delete_running_struct(rp);
1163 971 }
1164 972 }
1165 973 }
1166 974
1167 975 /*
1168 976 * set_conditionals(cnt, targets)
1169 977 *
1170 978 * Sets the conditional macros for the targets given in the array of
1171 979 * targets. The old macro values are returned in an array of
1172 980 * Properties for later resetting.
1173 981 *
1174 982 * Return value:
1175 983 * Array of conditional macro settings
1176 984 *
1177 985 * Parameters:
1178 986 * cnt Number of targets
1179 987 * targets Array of targets
1180 988 */
1181 989 static Property *
1182 990 set_conditionals(int cnt, Name *targets)
1183 991 {
1184 992 Property *locals, *lp;
1185 993 Name *tp;
1186 994
1187 995 locals = (Property *) getmem(cnt * sizeof(Property));
1188 996 for (lp = locals, tp = targets;
1189 997 cnt > 0;
1190 998 cnt--, lp++, tp++) {
1191 999 *lp = (Property) getmem((*tp)->conditional_cnt *
1192 1000 sizeof(struct _Property));
1193 1001 set_locals(*tp, *lp);
1194 1002 }
1195 1003 return locals;
1196 1004 }
1197 1005
1198 1006 /*
1199 1007 * reset_conditionals(cnt, targets, locals)
1200 1008 *
1201 1009 * Resets the conditional macros as saved in the given array of
1202 1010 * Properties. The resets are done in reverse order. Afterwards the
1203 1011 * data structures are freed.
1204 1012 *
1205 1013 * Parameters:
1206 1014 * cnt Number of targets
1207 1015 * targets Array of targets
1208 1016 * locals Array of dependency macro settings
1209 1017 */
1210 1018 static void
1211 1019 reset_conditionals(int cnt, Name *targets, Property *locals)
1212 1020 {
1213 1021 Name *tp;
1214 1022 Property *lp;
1215 1023
1216 1024 for (tp = targets + (cnt - 1), lp = locals + (cnt - 1);
1217 1025 cnt > 0;
1218 1026 cnt--, tp--, lp--) {
1219 1027 reset_locals(*tp,
1220 1028 *lp,
1221 1029 get_prop((*tp)->prop, conditional_prop),
1222 1030 0);
1223 1031 retmem_mb((caddr_t) *lp);
1224 1032 }
1225 1033 retmem_mb((caddr_t) locals);
1226 1034 }
1227 1035
1228 1036 /*
1229 1037 * dependency_conflict(target)
1230 1038 *
1231 1039 * Returns true if there is an intersection between
1232 1040 * the subtree of the target and any dependents of the pending targets.
1233 1041 *
1234 1042 * Return value:
1235 1043 * True if conflict found
1236 1044 *
1237 1045 * Parameters:
1238 1046 * target Subtree target to check
1239 1047 *
1240 1048 * Static variables used:
1241 1049 * subtree_conflict Target conflict found
1242 1050 * subtree_conflict2 Second conflict found
1243 1051 *
1244 1052 * Global variables used:
1245 1053 * running_list List of running processes
1246 1054 * wait_name .WAIT, not a real dependency
1247 1055 */
1248 1056 static Boolean
1249 1057 dependency_conflict(Name target)
1250 1058 {
1251 1059 Property line;
1252 1060 Property pending_line;
1253 1061 Dependency dp;
1254 1062 Dependency pending_dp;
1255 1063 Running rp;
1256 1064
1257 1065 /* Return if we are already checking this target */
1258 1066 if (target->checking_subtree) {
1259 1067 return false;
1260 1068 }
1261 1069 target->checking_subtree = true;
1262 1070 line = get_prop(target->prop, line_prop);
1263 1071 if (line == NULL) {
1264 1072 target->checking_subtree = false;
1265 1073 return false;
1266 1074 }
1267 1075 /* Check each dependency of the target for conflicts */
1268 1076 for (dp = line->body.line.dependencies; dp != NULL; dp = dp->next) {
1269 1077 /* Ignore .WAIT dependency */
1270 1078 if (dp->name == wait_name) {
1271 1079 continue;
1272 1080 }
1273 1081 /*
1274 1082 * For each pending target, look for a dependency which
1275 1083 * is the same as a dependency of the subtree target. Since
1276 1084 * we can't build the subtree until all pending targets have
1277 1085 * finished which depend on the same dependency, this is
1278 1086 * a conflict.
1279 1087 */
1280 1088 for (rp = running_list; rp != NULL; rp = rp->next) {
1281 1089 if (rp->state == build_pending) {
1282 1090 pending_line = get_prop(rp->target->prop,
1283 1091 line_prop);
1284 1092 if (pending_line == NULL) {
1285 1093 continue;
1286 1094 }
1287 1095 for(pending_dp = pending_line->
1288 1096 body.line.dependencies;
1289 1097 pending_dp != NULL;
1290 1098 pending_dp = pending_dp->next) {
1291 1099 if (dp->name == pending_dp->name) {
1292 1100 target->checking_subtree
1293 1101 = false;
1294 1102 subtree_conflict = rp->target;
1295 1103 subtree_conflict2 = dp->name;
1296 1104 return true;
1297 1105 }
1298 1106 }
1299 1107 }
1300 1108 }
1301 1109 if (dependency_conflict(dp->name)) {
1302 1110 target->checking_subtree = false;
1303 1111 return true;
1304 1112 }
1305 1113 }
1306 1114 target->checking_subtree = false;
1307 1115 return false;
1308 1116 }
1309 1117
1310 1118 /*
1311 1119 * await_parallel(waitflg)
1312 1120 *
1313 1121 * Waits for parallel children to exit and finishes their processing.
1314 1122 * If waitflg is false, the function returns after update_delay.
1315 1123 *
1316 1124 * Parameters:
1317 1125 * waitflg dwight
1318 1126 */
1319 1127 void
1320 1128 await_parallel(Boolean waitflg)
1321 1129 {
1322 1130 Boolean nohang;
1323 1131 pid_t pid;
1324 1132 int status;
1325 1133 Running rp;
1326 1134 int waiterr;
1327 1135
1328 1136 nohang = false;
1329 1137 for ( ; ; ) {
1330 1138 if (!nohang) {
1331 1139 (void) alarm((int) update_delay);
1332 1140 }
1333 1141 pid = waitpid((pid_t)-1,
1334 1142 &status,
1335 1143 nohang ? WNOHANG : 0);
1336 1144 waiterr = errno;
1337 1145 if (!nohang) {
1338 1146 (void) alarm(0);
1339 1147 }
1340 1148 if (pid <= 0) {
1341 1149 if (waiterr == EINTR) {
1342 1150 if (waitflg) {
1343 1151 continue;
1344 1152 } else {
1345 1153 return;
1346 1154 }
1347 1155 } else {
1348 1156 return;
1349 1157 }
1350 1158 }
1351 1159 for (rp = running_list;
1352 1160 (rp != NULL) && (rp->pid != pid);
1353 1161 rp = rp->next) {
1354 1162 ;
1355 1163 }
1356 1164 if (rp == NULL) {
1357 1165 if (send_mtool_msgs) {
1358 1166 continue;
1359 1167 } else {
1360 1168 fatal(catgets(catd, 1, 128, "Internal error: returned child pid not in running_list"));
1361 1169 }
1362 1170 } else {
1363 1171 rp->state = (WIFEXITED(status) && WEXITSTATUS(status) == 0) ? build_ok : build_failed;
1364 1172 }
1365 1173 nohang = true;
1366 1174 parallel_process_cnt--;
1367 1175
1368 1176 #if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000)
1369 1177 if (job_adjust_mode == ADJUST_M2) {
1370 1178 if (m2_release_job()) {
1371 1179 job_adjust_error();
1372 1180 }
1373 1181 }
1374 1182 #endif
1375 1183 }
1376 1184 }
1377 1185
1378 1186 /*
1379 1187 * finish_children(docheck)
1380 1188 *
1381 1189 * Finishes the processing for all targets which were running
1382 1190 * and have now completed.
1383 1191 *
1384 1192 * Parameters:
1385 1193 * docheck Completely check the finished target
1386 1194 *
1387 1195 * Static variables used:
1388 1196 * running_tail The tail of the running list
1389 1197 *
1390 1198 * Global variables used:
1391 1199 * continue_after_error -k flag
1392 1200 * fatal_in_progress True if we are finishing up after fatal err
1393 1201 * running_list List of running processes
1394 1202 */
1395 1203 void
1396 1204 finish_children(Boolean docheck)
1397 1205 {
1398 1206 int cmds_length;
1399 1207 Property line;
1400 1208 Property line2;
1401 1209 struct stat out_buf;
1402 1210 Running rp;
1403 1211 Running *rp_prev;
1404 1212 Cmd_line rule;
1405 1213 Boolean silent_flag;
1406 1214
1407 1215 for (rp_prev = &running_list, rp = running_list;
1408 1216 rp != NULL;
1409 1217 rp = rp->next) {
1410 1218 bypass_for_loop_inc_4:
1411 1219 /*
1412 1220 * If the state is ok or failed, then this target has
1413 1221 * finished building.
1414 1222 * In parallel_mode, output the accumulated stdout/stderr.
1415 1223 * Read the auto dependency stuff, handle a failed build,
1416 1224 * update the target, then finish the doname process for
1417 1225 * that target.
1418 1226 */
1419 1227 if (rp->state == build_ok || rp->state == build_failed) {
1420 1228 *rp_prev = rp->next;
1421 1229 if (rp->next == NULL) {
1422 1230 running_tail = rp_prev;
↓ open down ↓ |
251 lines elided |
↑ open up ↑ |
1423 1231 }
1424 1232 if ((line2 = rp->command) == NULL) {
1425 1233 line2 = get_prop(rp->target->prop, line_prop);
1426 1234 }
1427 1235 if (dmake_mode_type == distributed_mode) {
1428 1236 if (rp->make_refd) {
1429 1237 maybe_reread_make_state();
1430 1238 }
1431 1239 } else {
1432 1240 /*
1433 - * Send an Avo_MToolJobResultMsg to maketool.
1434 - */
1435 -#ifdef DISTRIBUTED
1436 - if (send_mtool_msgs) {
1437 - send_job_result_msg(rp);
1438 - }
1439 -#endif
1440 - /*
1441 1241 * Check if there were any job output
1442 1242 * from the parallel build.
1443 1243 */
1444 1244 if (rp->stdout_file != NULL) {
1445 1245 if (stat(rp->stdout_file, &out_buf) < 0) {
1446 1246 fatal(catgets(catd, 1, 130, "stat of %s failed: %s"),
1447 1247 rp->stdout_file,
1448 1248 errmsg(errno));
1449 1249 }
1450 1250 if ((line2 != NULL) &&
1451 1251 (out_buf.st_size > 0)) {
1452 1252 cmds_length = 0;
1453 1253 for (rule = line2->body.line.command_used,
1454 1254 silent_flag = silent;
1455 1255 rule != NULL;
1456 1256 rule = rule->next) {
1457 1257 cmds_length += rule->command_line->hash.length + 1;
1458 1258 silent_flag = BOOLEAN(silent_flag || rule->silent);
1459 1259 }
1460 1260 if (out_buf.st_size != cmds_length || silent_flag ||
1461 1261 output_mode == txt2_mode) {
1462 1262 dump_out_file(rp->stdout_file, false);
1463 1263 }
1464 1264 }
1465 1265 (void) unlink(rp->stdout_file);
1466 1266 retmem_mb(rp->stdout_file);
1467 1267 rp->stdout_file = NULL;
1468 1268 }
1469 1269
1470 1270 if (!out_err_same && (rp->stderr_file != NULL)) {
1471 1271 if (stat(rp->stderr_file, &out_buf) < 0) {
1472 1272 fatal(catgets(catd, 1, 130, "stat of %s failed: %s"),
1473 1273 rp->stderr_file,
1474 1274 errmsg(errno));
1475 1275 }
1476 1276 if ((line2 != NULL) &&
1477 1277 (out_buf.st_size > 0)) {
1478 1278 dump_out_file(rp->stderr_file, true);
1479 1279 }
1480 1280 (void) unlink(rp->stderr_file);
1481 1281 retmem_mb(rp->stderr_file);
1482 1282 rp->stderr_file = NULL;
1483 1283 }
1484 1284 }
1485 1285 check_state(rp->temp_file);
1486 1286 if (rp->temp_file != NULL) {
1487 1287 free_name(rp->temp_file);
1488 1288 }
1489 1289 rp->temp_file = NULL;
1490 1290 if (rp->state == build_failed) {
1491 1291 line = get_prop(rp->target->prop, line_prop);
1492 1292 if (line != NULL) {
1493 1293 line->body.line.command_used = NULL;
1494 1294 }
1495 1295 if (continue_after_error ||
1496 1296 fatal_in_progress ||
1497 1297 !docheck) {
1498 1298 warning(catgets(catd, 1, 256, "Command failed for target `%s'"),
1499 1299 rp->command ? line2->body.line.target->string_mb : rp->target->string_mb);
1500 1300 build_failed_seen = true;
1501 1301 } else {
1502 1302 /*
1503 1303 * XXX??? - DMake needs to exit(),
1504 1304 * but shouldn't call fatal().
1505 1305 */
1506 1306 #ifdef PRINT_EXIT_STATUS
1507 1307 warning(NOCATGETS("I'm in finish_children. rp->state == build_failed."));
1508 1308 #endif
1509 1309
1510 1310 fatal(catgets(catd, 1, 258, "Command failed for target `%s'"),
1511 1311 rp->command ? line2->body.line.target->string_mb : rp->target->string_mb);
1512 1312 }
1513 1313 }
1514 1314 if (!docheck) {
1515 1315 delete_running_struct(rp);
1516 1316 rp = *rp_prev;
1517 1317 if (rp == NULL) {
1518 1318 break;
1519 1319 } else {
1520 1320 goto bypass_for_loop_inc_4;
1521 1321 }
1522 1322 }
1523 1323 update_target(get_prop(rp->target->prop, line_prop),
1524 1324 rp->state);
1525 1325 finish_doname(rp);
1526 1326 delete_running_struct(rp);
1527 1327 rp = *rp_prev;
1528 1328 if (rp == NULL) {
1529 1329 break;
1530 1330 } else {
1531 1331 goto bypass_for_loop_inc_4;
1532 1332 }
1533 1333 } else {
1534 1334 rp_prev = &rp->next;
1535 1335 }
1536 1336 }
1537 1337 }
1538 1338
1539 1339 /*
1540 1340 * dump_out_file(filename, err)
1541 1341 *
1542 1342 * Write the contents of the file to stdout, then unlink the file.
1543 1343 *
1544 1344 * Parameters:
1545 1345 * filename Name of temp file containing output
1546 1346 *
1547 1347 * Global variables used:
1548 1348 */
1549 1349 static void
1550 1350 dump_out_file(char *filename, Boolean err)
1551 1351 {
1552 1352 int chars_read;
1553 1353 char copybuf[BUFSIZ];
1554 1354 int fd;
1555 1355 int out_fd = (err ? 2 : 1);
1556 1356
1557 1357 if ((fd = open(filename, O_RDONLY)) < 0) {
1558 1358 fatal(catgets(catd, 1, 141, "open failed for output file %s: %s"),
1559 1359 filename,
1560 1360 errmsg(errno));
1561 1361 }
1562 1362 if (!silent && output_mode != txt2_mode) {
1563 1363 (void) fprintf(err ? stderr : stdout,
1564 1364 err ?
1565 1365 catgets(catd, 1, 338, "%s --> Job errors\n") :
1566 1366 catgets(catd, 1, 259, "%s --> Job output\n"),
1567 1367 local_host);
1568 1368 (void) fflush(err ? stderr : stdout);
1569 1369 }
1570 1370 for (chars_read = read(fd, copybuf, BUFSIZ);
1571 1371 chars_read > 0;
1572 1372 chars_read = read(fd, copybuf, BUFSIZ)) {
1573 1373 /*
1574 1374 * Read buffers from the source file until end or error.
1575 1375 */
1576 1376 if (write(out_fd, copybuf, chars_read) < 0) {
1577 1377 fatal(catgets(catd, 1, 260, "write failed for output file %s: %s"),
1578 1378 filename,
1579 1379 errmsg(errno));
1580 1380 }
1581 1381 }
1582 1382 (void) close(fd);
1583 1383 (void) unlink(filename);
1584 1384 }
1585 1385
1586 1386 /*
1587 1387 * finish_doname(rp)
1588 1388 *
1589 1389 * Completes the processing for a target which was left running.
1590 1390 *
1591 1391 * Parameters:
1592 1392 * rp Running list entry for target
1593 1393 *
1594 1394 * Global variables used:
1595 1395 * debug_level Debug flag
1596 1396 * recursion_level Indentation for debug output
1597 1397 */
1598 1398 static void
1599 1399 finish_doname(Running rp)
1600 1400 {
1601 1401 int auto_count = rp->auto_count;
1602 1402 Name *automatics = rp->automatics;
1603 1403 Doname result = rp->state;
1604 1404 Name target = rp->target;
1605 1405 Name true_target = rp->true_target;
1606 1406 Property *conditionals;
1607 1407
1608 1408 recursion_level = rp->recursion_level;
1609 1409 if (result == build_ok) {
1610 1410 if (true_target == NULL) {
1611 1411 (void) printf(NOCATGETS("Target = %s\n"), target->string_mb);
1612 1412 (void) printf(NOCATGETS(" State = %d\n"), result);
1613 1413 fatal(NOCATGETS("Internal error: NULL true_target in finish_doname"));
1614 1414 }
1615 1415 /* If all went OK, set a nice timestamp */
1616 1416 if (true_target->stat.time == file_doesnt_exist) {
1617 1417 true_target->stat.time = file_max_time;
1618 1418 }
1619 1419 }
1620 1420 target->state = result;
1621 1421 if (target->is_member) {
1622 1422 Property member;
1623 1423
1624 1424 /* Propagate the timestamp from the member file to the member */
1625 1425 if ((target->stat.time != file_max_time) &&
1626 1426 ((member = get_prop(target->prop, member_prop)) != NULL) &&
1627 1427 (exists(member->body.member.member) > file_doesnt_exist)) {
1628 1428 target->stat.time =
1629 1429 /*
1630 1430 exists(member->body.member.member);
1631 1431 */
1632 1432 member->body.member.member->stat.time;
1633 1433 }
1634 1434 }
1635 1435 /*
1636 1436 * Check if we found any new auto dependencies when we
1637 1437 * built the target.
1638 1438 */
1639 1439 if ((result == build_ok) && check_auto_dependencies(target,
1640 1440 auto_count,
1641 1441 automatics)) {
1642 1442 if (debug_level > 0) {
1643 1443 (void) printf(catgets(catd, 1, 261, "%*sTarget `%s' acquired new dependencies from build, checking all dependencies\n"),
1644 1444 recursion_level,
1645 1445 "",
1646 1446 true_target->string_mb);
1647 1447 }
1648 1448 target->rechecking_target = true;
1649 1449 target->state = build_running;
1650 1450
1651 1451 /* [tolik, Tue Mar 25 1997]
1652 1452 * Fix for bug 4038824:
1653 1453 * command line options set by conditional macros get dropped
1654 1454 * rp->conditional_cnt and rp->conditional_targets must be copied
1655 1455 * to new 'rp' during add_pending(). Set_conditionals() stores
1656 1456 * rp->conditional_targets to the global variable 'conditional_targets'
1657 1457 * Add_pending() will use this variable to set up 'rp'.
1658 1458 */
1659 1459 conditionals = set_conditionals(rp->conditional_cnt, rp->conditional_targets);
1660 1460 add_pending(target,
1661 1461 recursion_level,
1662 1462 rp->do_get,
1663 1463 rp->implicit,
1664 1464 true);
1665 1465 reset_conditionals(rp->conditional_cnt, rp->conditional_targets, conditionals);
1666 1466 }
1667 1467 }
1668 1468
1669 1469 /*
1670 1470 * new_running_struct()
1671 1471 *
1672 1472 * Constructor for Running struct. Creates a structure and initializes
1673 1473 * its fields.
1674 1474 *
1675 1475 */
1676 1476 static Running new_running_struct()
1677 1477 {
1678 1478 Running rp;
1679 1479
1680 1480 rp = ALLOC(Running);
1681 1481 rp->target = NULL;
1682 1482 rp->true_target = NULL;
1683 1483 rp->command = NULL;
1684 1484 rp->sprodep_value = NULL;
1685 1485 rp->sprodep_env = NULL;
1686 1486 rp->auto_count = 0;
1687 1487 rp->automatics = NULL;
1688 1488 rp->pid = -1;
1689 1489 rp->job_msg_id = -1;
1690 1490 rp->stdout_file = NULL;
1691 1491 rp->stderr_file = NULL;
1692 1492 rp->temp_file = NULL;
1693 1493 rp->next = NULL;
1694 1494 return rp;
1695 1495 }
1696 1496
1697 1497 /*
1698 1498 * add_running(target, true_target, command, recursion_level, auto_count,
1699 1499 * automatics, do_get, implicit)
1700 1500 *
1701 1501 * Adds a record on the running list for this target, which
1702 1502 * was just spawned and is running.
1703 1503 *
1704 1504 * Parameters:
1705 1505 * target Target being built
1706 1506 * true_target True target for target
1707 1507 * command Running command.
1708 1508 * recursion_level Debug indentation level
1709 1509 * auto_count Count of automatic dependencies
1710 1510 * automatics List of automatic dependencies
1711 1511 * do_get Sccs get flag
1712 1512 * implicit Implicit flag
1713 1513 *
1714 1514 * Static variables used:
1715 1515 * running_tail Tail of running list
1716 1516 * process_running PID of process
1717 1517 *
1718 1518 * Global variables used:
1719 1519 * current_line Current line for target
1720 1520 * current_target Current target being built
1721 1521 * stderr_file Temporary file for stdout
1722 1522 * stdout_file Temporary file for stdout
1723 1523 * temp_file_name Temporary file for auto dependencies
1724 1524 */
1725 1525 void
1726 1526 add_running(Name target, Name true_target, Property command, int recursion_level, int auto_count, Name *automatics, Boolean do_get, Boolean implicit)
1727 1527 {
1728 1528 Running rp;
1729 1529 Name *p;
1730 1530
1731 1531 rp = new_running_struct();
1732 1532 rp->state = build_running;
1733 1533 rp->target = target;
1734 1534 rp->true_target = true_target;
1735 1535 rp->command = command;
1736 1536 rp->recursion_level = recursion_level;
1737 1537 rp->do_get = do_get;
↓ open down ↓ |
287 lines elided |
↑ open up ↑ |
1738 1538 rp->implicit = implicit;
1739 1539 rp->auto_count = auto_count;
1740 1540 if (auto_count > 0) {
1741 1541 rp->automatics = (Name *) getmem(auto_count * sizeof (Name));
1742 1542 for (p = rp->automatics; auto_count > 0; auto_count--) {
1743 1543 *p++ = *automatics++;
1744 1544 }
1745 1545 } else {
1746 1546 rp->automatics = NULL;
1747 1547 }
1748 -#ifdef DISTRIBUTED
1749 - if (dmake_mode_type == distributed_mode) {
1750 - rp->make_refd = called_make;
1751 - called_make = false;
1752 - } else
1753 -#endif
1754 1548 {
1755 1549 rp->pid = process_running;
1756 1550 process_running = -1;
1757 1551 childPid = -1;
1758 1552 }
1759 1553 rp->job_msg_id = job_msg_id;
1760 1554 rp->stdout_file = stdout_file;
1761 1555 rp->stderr_file = stderr_file;
1762 1556 rp->temp_file = temp_file_name;
1763 1557 rp->redo = false;
1764 1558 rp->next = NULL;
1765 1559 store_conditionals(rp);
1766 1560 stdout_file = NULL;
1767 1561 stderr_file = NULL;
1768 1562 temp_file_name = NULL;
1769 1563 current_target = NULL;
1770 1564 current_line = NULL;
1771 1565 *running_tail = rp;
1772 1566 running_tail = &rp->next;
1773 1567 }
1774 1568
1775 1569 /*
1776 1570 * add_pending(target, recursion_level, do_get, implicit, redo)
1777 1571 *
1778 1572 * Adds a record on the running list for a pending target
1779 1573 * (waiting for its dependents to finish running).
1780 1574 *
1781 1575 * Parameters:
1782 1576 * target Target being built
1783 1577 * recursion_level Debug indentation level
1784 1578 * do_get Sccs get flag
1785 1579 * implicit Implicit flag
1786 1580 * redo True if this target is being redone
1787 1581 *
1788 1582 * Static variables used:
1789 1583 * running_tail Tail of running list
1790 1584 */
1791 1585 void
1792 1586 add_pending(Name target, int recursion_level, Boolean do_get, Boolean implicit, Boolean redo)
1793 1587 {
1794 1588 Running rp;
1795 1589 rp = new_running_struct();
1796 1590 rp->state = build_pending;
1797 1591 rp->target = target;
1798 1592 rp->recursion_level = recursion_level;
1799 1593 rp->do_get = do_get;
1800 1594 rp->implicit = implicit;
1801 1595 rp->redo = redo;
1802 1596 store_conditionals(rp);
1803 1597 *running_tail = rp;
1804 1598 running_tail = &rp->next;
1805 1599 }
1806 1600
1807 1601 /*
1808 1602 * add_serial(target, recursion_level, do_get, implicit)
1809 1603 *
1810 1604 * Adds a record on the running list for a target which must be
1811 1605 * executed in serial after others have finished.
1812 1606 *
1813 1607 * Parameters:
1814 1608 * target Target being built
1815 1609 * recursion_level Debug indentation level
1816 1610 * do_get Sccs get flag
1817 1611 * implicit Implicit flag
1818 1612 *
1819 1613 * Static variables used:
1820 1614 * running_tail Tail of running list
1821 1615 */
1822 1616 void
1823 1617 add_serial(Name target, int recursion_level, Boolean do_get, Boolean implicit)
1824 1618 {
1825 1619 Running rp;
1826 1620
1827 1621 rp = new_running_struct();
1828 1622 rp->target = target;
1829 1623 rp->recursion_level = recursion_level;
1830 1624 rp->do_get = do_get;
1831 1625 rp->implicit = implicit;
1832 1626 rp->state = build_serial;
1833 1627 rp->redo = false;
1834 1628 store_conditionals(rp);
1835 1629 *running_tail = rp;
1836 1630 running_tail = &rp->next;
1837 1631 }
1838 1632
1839 1633 /*
1840 1634 * add_subtree(target, recursion_level, do_get, implicit)
1841 1635 *
1842 1636 * Adds a record on the running list for a target which must be
1843 1637 * executed in isolation after others have finished.
1844 1638 *
1845 1639 * Parameters:
1846 1640 * target Target being built
1847 1641 * recursion_level Debug indentation level
1848 1642 * do_get Sccs get flag
1849 1643 * implicit Implicit flag
1850 1644 *
1851 1645 * Static variables used:
1852 1646 * running_tail Tail of running list
1853 1647 */
1854 1648 void
1855 1649 add_subtree(Name target, int recursion_level, Boolean do_get, Boolean implicit)
1856 1650 {
1857 1651 Running rp;
1858 1652
1859 1653 rp = new_running_struct();
1860 1654 rp->target = target;
1861 1655 rp->recursion_level = recursion_level;
1862 1656 rp->do_get = do_get;
1863 1657 rp->implicit = implicit;
1864 1658 rp->state = build_subtree;
1865 1659 rp->redo = false;
1866 1660 store_conditionals(rp);
1867 1661 *running_tail = rp;
1868 1662 running_tail = &rp->next;
1869 1663 }
1870 1664
1871 1665 /*
1872 1666 * store_conditionals(rp)
1873 1667 *
1874 1668 * Creates an array of the currently active targets with conditional
1875 1669 * macros (found in the chain conditional_targets) and puts that
1876 1670 * array in the Running struct.
1877 1671 *
1878 1672 * Parameters:
1879 1673 * rp Running struct for storing chain
1880 1674 *
1881 1675 * Global variables used:
1882 1676 * conditional_targets Chain of current dynamic conditionals
1883 1677 */
1884 1678 static void
1885 1679 store_conditionals(Running rp)
1886 1680 {
1887 1681 int cnt;
1888 1682 Chain cond_name;
1889 1683
1890 1684 if (conditional_targets == NULL) {
1891 1685 rp->conditional_cnt = 0;
1892 1686 rp->conditional_targets = NULL;
1893 1687 return;
1894 1688 }
1895 1689 cnt = 0;
1896 1690 for (cond_name = conditional_targets;
1897 1691 cond_name != NULL;
1898 1692 cond_name = cond_name->next) {
1899 1693 cnt++;
1900 1694 }
1901 1695 rp->conditional_cnt = cnt;
1902 1696 rp->conditional_targets = (Name *) getmem(cnt * sizeof(Name));
1903 1697 for (cond_name = conditional_targets;
1904 1698 cond_name != NULL;
1905 1699 cond_name = cond_name->next) {
1906 1700 rp->conditional_targets[--cnt] = cond_name->name;
1907 1701 }
1908 1702 }
1909 1703
1910 1704 /*
1911 1705 * parallel_ok(target, line_prop_must_exists)
1912 1706 *
1913 1707 * Returns true if the target can be run in parallel
1914 1708 *
1915 1709 * Return value:
1916 1710 * True if can run in parallel
1917 1711 *
1918 1712 * Parameters:
1919 1713 * target Target being tested
1920 1714 *
1921 1715 * Global variables used:
1922 1716 * all_parallel True if all targets default to parallel
1923 1717 * only_parallel True if no targets default to parallel
1924 1718 */
1925 1719 Boolean
1926 1720 parallel_ok(Name target, Boolean line_prop_must_exists)
1927 1721 {
1928 1722 Boolean assign;
1929 1723 Boolean make_refd;
1930 1724 Property line;
1931 1725 Cmd_line rule;
1932 1726
1933 1727 assign = make_refd = false;
1934 1728 if (((line = get_prop(target->prop, line_prop)) == NULL) &&
1935 1729 line_prop_must_exists) {
1936 1730 return false;
1937 1731 }
1938 1732 if (line != NULL) {
1939 1733 for (rule = line->body.line.command_used;
1940 1734 rule != NULL;
1941 1735 rule = rule->next) {
1942 1736 if (rule->assign) {
1943 1737 assign = true;
1944 1738 } else if (rule->make_refd) {
1945 1739 make_refd = true;
1946 1740 }
1947 1741 }
1948 1742 }
1949 1743 if (assign) {
1950 1744 return false;
1951 1745 } else if (target->parallel) {
1952 1746 return true;
1953 1747 } else if (target->no_parallel) {
1954 1748 return false;
1955 1749 } else if (all_parallel) {
1956 1750 return true;
1957 1751 } else if (only_parallel) {
1958 1752 return false;
1959 1753 } else if (make_refd) {
1960 1754 return false;
1961 1755 } else {
1962 1756 return true;
1963 1757 }
1964 1758 }
1965 1759
1966 1760 /*
1967 1761 * is_running(target)
1968 1762 *
1969 1763 * Returns true if the target is running.
1970 1764 *
1971 1765 * Return value:
1972 1766 * True if target is running
1973 1767 *
1974 1768 * Parameters:
1975 1769 * target Target to check
1976 1770 *
1977 1771 * Global variables used:
1978 1772 * running_list List of running processes
1979 1773 */
1980 1774 Boolean
1981 1775 is_running(Name target)
1982 1776 {
1983 1777 Running rp;
1984 1778
1985 1779 if (target->state != build_running) {
1986 1780 return false;
1987 1781 }
1988 1782 for (rp = running_list;
1989 1783 rp != NULL && target != rp->target;
1990 1784 rp = rp->next);
1991 1785 if (rp == NULL) {
1992 1786 return false;
1993 1787 } else {
1994 1788 return (rp->state == build_running) ? true : false;
1995 1789 }
1996 1790 }
1997 1791
1998 1792 /*
1999 1793 * This function replaces the makesh binary.
2000 1794 */
2001 1795
2002 1796
2003 1797 static pid_t
2004 1798 run_rule_commands(char *host, char **commands)
2005 1799 {
2006 1800 Boolean always_exec;
2007 1801 Name command;
2008 1802 Boolean ignore;
2009 1803 int length;
2010 1804 Doname result;
2011 1805 Boolean silent_flag;
2012 1806 wchar_t *tmp_wcs_buffer;
2013 1807
2014 1808 childPid = fork();
2015 1809 switch (childPid) {
2016 1810 case -1: /* Error */
2017 1811 fatal(catgets(catd, 1, 337, "Could not fork child process for dmake job: %s"),
2018 1812 errmsg(errno));
2019 1813 break;
2020 1814 case 0: /* Child */
2021 1815 /* To control the processed targets list is not the child's business */
2022 1816 running_list = NULL;
2023 1817 if(out_err_same) {
2024 1818 redirect_io(stdout_file, (char*)NULL);
2025 1819 } else {
2026 1820 redirect_io(stdout_file, stderr_file);
2027 1821 }
2028 1822 for (commands = commands;
2029 1823 (*commands != (char *)NULL);
2030 1824 commands++) {
2031 1825 silent_flag = silent;
2032 1826 ignore = false;
2033 1827 always_exec = false;
2034 1828 while ((**commands == (int) at_char) ||
2035 1829 (**commands == (int) hyphen_char) ||
2036 1830 (**commands == (int) plus_char)) {
2037 1831 if (**commands == (int) at_char) {
2038 1832 silent_flag = true;
2039 1833 }
2040 1834 if (**commands == (int) hyphen_char) {
2041 1835 ignore = true;
2042 1836 }
2043 1837 if (**commands == (int) plus_char) {
2044 1838 always_exec = true;
2045 1839 }
2046 1840 (*commands)++;
2047 1841 }
2048 1842 if ((length = strlen(*commands)) >= MAXPATHLEN) {
2049 1843 tmp_wcs_buffer = ALLOC_WC(length + 1);
2050 1844 (void) mbstowcs(tmp_wcs_buffer, *commands, length + 1);
2051 1845 command = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
2052 1846 retmem(tmp_wcs_buffer);
2053 1847 } else {
2054 1848 MBSTOWCS(wcs_buffer, *commands);
2055 1849 command = GETNAME(wcs_buffer, FIND_LENGTH);
2056 1850 }
2057 1851 if ((command->hash.length > 0) &&
2058 1852 !silent_flag) {
2059 1853 (void) printf("%s\n", command->string_mb);
2060 1854 }
2061 1855 result = dosys(command,
2062 1856 ignore,
2063 1857 false,
2064 1858 false, /* bugs #4085164 & #4990057 */
2065 1859 /* BOOLEAN(silent_flag && ignore), */
2066 1860 always_exec,
2067 1861 (Name) NULL,
2068 1862 false);
2069 1863 if (result == build_failed) {
2070 1864 if (silent_flag) {
2071 1865 (void) printf(catgets(catd, 1, 152, "The following command caused the error:\n%s\n"), command->string_mb);
2072 1866 }
2073 1867 if (!ignore) {
2074 1868 _exit(1);
2075 1869 }
2076 1870 }
2077 1871 }
2078 1872 _exit(0);
2079 1873 break;
2080 1874 default:
2081 1875 break;
2082 1876 }
2083 1877 return childPid;
2084 1878 }
2085 1879
2086 1880 static void
2087 1881 maybe_reread_make_state(void)
2088 1882 {
2089 1883 /* Copying dosys()... */
2090 1884 if (report_dependencies_level == 0) {
2091 1885 make_state->stat.time = file_no_time;
2092 1886 (void) exists(make_state);
2093 1887 if (make_state_before == make_state->stat.time) {
2094 1888 return;
2095 1889 }
2096 1890 makefile_type = reading_statefile;
2097 1891 if (read_trace_level > 1) {
2098 1892 trace_reader = true;
2099 1893 }
2100 1894 temp_file_number++;
2101 1895 (void) read_simple_file(make_state,
↓ open down ↓ |
338 lines elided |
↑ open up ↑ |
2102 1896 false,
2103 1897 false,
2104 1898 false,
2105 1899 false,
2106 1900 false,
2107 1901 true);
2108 1902 trace_reader = false;
2109 1903 }
2110 1904 }
2111 1905
2112 -#ifdef DISTRIBUTED
2113 -/*
2114 - * Create and send an Avo_MToolJobResultMsg.
2115 - */
2116 -static void
2117 -send_job_result_msg(Running rp)
2118 -{
2119 - Avo_MToolJobResultMsg *msg;
2120 - RWCollectable *xdr_msg;
2121 -
2122 - msg = new Avo_MToolJobResultMsg();
2123 - msg->setResult(rp->job_msg_id,
2124 - (rp->state == build_ok) ? 0 : 1,
2125 - DONE);
2126 - append_job_result_msg(msg,
2127 - rp->stdout_file,
2128 - rp->stderr_file);
2129 -
2130 - xdr_msg = (RWCollectable *)msg;
2131 - xdr(get_xdrs_ptr(), xdr_msg);
2132 - (void) fflush(get_mtool_msgs_fp());
2133 -
2134 - delete msg;
2135 -}
2136 -
2137 -/*
2138 - * Append the stdout/err to Avo_MToolJobResultMsg.
2139 - */
2140 -static void
2141 -append_job_result_msg(Avo_MToolJobResultMsg *msg, char *outFn, char *errFn)
2142 -{
2143 - FILE *fp;
2144 - char line[MAXPATHLEN];
2145 -
2146 - fp = fopen(outFn, "r");
2147 - if (fp == NULL) {
2148 - /* Hmmm... what should we do here? */
2149 - return;
2150 - }
2151 - while (fgets(line, MAXPATHLEN, fp) != NULL) {
2152 - if (line[strlen(line) - 1] == '\n') {
2153 - line[strlen(line) - 1] = '\0';
2154 - }
2155 - msg->appendOutput(AVO_STRDUP(line));
2156 - }
2157 - (void) fclose(fp);
2158 -}
2159 -#endif
2160 1906
2161 1907 static void
2162 1908 delete_running_struct(Running rp)
2163 1909 {
2164 1910 if ((rp->conditional_cnt > 0) &&
2165 1911 (rp->conditional_targets != NULL)) {
2166 1912 retmem_mb((char *) rp->conditional_targets);
2167 1913 }
2168 1914 /**/
2169 1915 if ((rp->auto_count > 0) &&
2170 1916 (rp->automatics != NULL)) {
2171 1917 retmem_mb((char *) rp->automatics);
2172 1918 }
2173 1919 /**/
2174 1920 if(rp->sprodep_value) {
2175 1921 free_name(rp->sprodep_value);
2176 1922 }
2177 1923 if(rp->sprodep_env) {
2178 1924 retmem_mb(rp->sprodep_env);
2179 1925 }
2180 1926 retmem_mb((char *) rp);
2181 1927
2182 1928 }
2183 1929
2184 1930 #endif
2185 1931
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX