*/
is_limited_fork = 0;
+ /*
+ * Close unused ends of the job control pipes. Only the parent
+ * which controls the jobs may have the write end open of the
+ * job_get_permission_fd and the read end of the
+ * job_request_fd. Failing to close the pipe ends properly
+ * will cause the childs to wait forever for the run
+ * permission in case parent dies prematurely.
+ *
+ * Note! The file descriptor must be closed once and only
+ * once. They are marked to -1 to make it impossible for
+ * subseqent do_fork() calls from closing them again (in which
+ * case some other file descriptor might already be reserved
+ * for the same number) and prevent accidentally closing some
+ * innocent file descriptors that are still in use.
+ */
+ if (job_get_permission_fd[1] >= 0) {
+ close(job_get_permission_fd[1]);
+ job_get_permission_fd[1] = -1;
+ }
+ if (job_request_fd[0] >= 0) {
+ close(job_request_fd[0]);
+ job_request_fd[0] = -1;
+ }
+
/* reset child's child count */
child_count = 0;
parent_count++;
/*
* The parent will tell us when we can continue. If there were
- * multiple children waiting for their turn to run parent's
- * write to the pipe will wake up every process reading
- * it. However, only one will be reading the content and
- * getting the permission to run. So we will read as many
- * times as needed until we get our own permission to run.
+ * multiple children waiting for their turn to run only one
+ * will be reading the content byte from the pipe and getting
+ * the permission to run.
*/
- do {
- ret = read(job_get_permission_fd[0], &byte, sizeof(byte));
- if (ret == 1)
- break;
+ ret = read(job_get_permission_fd[0], &byte, sizeof(byte));
+ if (ret == 0)
+ pr_err("Error requesting run, did the parent die?\n");
- } while(1);
+ if (ret < 0)
+ pr_err("Job control request failure: %m\n");
pr_info("Continuing\n");
return child;