| 2856 | |
| 2857 | |
| 2858 | UPID ProcessManager::spawn(ProcessBase* process, bool manage) |
| 2859 | { |
| 2860 | CHECK_NOTNULL(process); |
| 2861 | |
| 2862 | bool spawned = false; |
| 2863 | |
| 2864 | // If the `ProcessManager` is cleaning itself up, no further processes |
| 2865 | // may be spawned. |
| 2866 | if (finalizing.load()) { |
| 2867 | LOG(WARNING) |
| 2868 | << "Attempted to spawn a process (" << process->self() |
| 2869 | << ") after finalizing libprocess!"; |
| 2870 | } else if (process->state.load() != ProcessBase::State::BOTTOM) { |
| 2871 | LOG(WARNING) |
| 2872 | << "Attempted to spawn a process (" << process->self() |
| 2873 | << ") that has already been initialized"; |
| 2874 | } else { |
| 2875 | synchronized (processes_mutex) { |
| 2876 | if (processes.count(process->pid.id) > 0) { |
| 2877 | LOG(WARNING) |
| 2878 | << "Attempted to spawn already running process " << process->pid; |
| 2879 | } else { |
| 2880 | processes[process->pid.id] = process; |
| 2881 | |
| 2882 | // NOTE: we set process reference on it's `UPID` _after_ we've |
| 2883 | // spawned so that we make sure that we'll take the |
| 2884 | // `ProcessManager::use()` code path in the event that we |
| 2885 | // aren't able to spawn the process. This is important in |
| 2886 | // circumstances where there are multiple processes with the |
| 2887 | // same ID because the semantics that people have come to |
| 2888 | // expect from libprocess is that a `UPID` should "resolve" to |
| 2889 | // the already spawned process rather than a process that has |
| 2890 | // the same name but hasn't yet been spawned. |
| 2891 | process->pid.reference = process->reference; |
| 2892 | |
| 2893 | spawned = true; |
| 2894 | } |
| 2895 | } |
| 2896 | } |
| 2897 | |
| 2898 | if (!spawned) { |
| 2899 | if (manage) { |
| 2900 | delete process; |
| 2901 | } |
| 2902 | return UPID(); |
| 2903 | } |
| 2904 | |
| 2905 | if (manage) { |
| 2906 | process->manage = true; |
| 2907 | } |
| 2908 | |
| 2909 | // We save the PID before enqueueing the process to avoid the race |
| 2910 | // condition that occurs when a user has a very short process and |
| 2911 | // the process gets run and cleaned up before we return from enqueue |
| 2912 | // (e.g., when 'manage' is set to true). |
| 2913 | UPID pid = process->self(); |
| 2914 | |
| 2915 | // Add process to the run queue (so 'initialize' will get invoked). |