| 2922 | |
| 2923 | |
| 2924 | void ProcessManager::resume(ProcessBase* process) |
| 2925 | { |
| 2926 | __process__ = process; |
| 2927 | |
| 2928 | VLOG(3) << "Resuming " << process->pid << " at " << Clock::now(); |
| 2929 | |
| 2930 | bool manage = process->manage; |
| 2931 | bool terminate = false; |
| 2932 | bool blocked = false; |
| 2933 | |
| 2934 | ProcessBase::State state = process->state.load(); |
| 2935 | |
| 2936 | CHECK(state == ProcessBase::State::BOTTOM || |
| 2937 | state == ProcessBase::State::READY); |
| 2938 | |
| 2939 | if (state == ProcessBase::State::BOTTOM) { |
| 2940 | // In the event that the process throws an exception, |
| 2941 | // we will abort the program. |
| 2942 | // |
| 2943 | // TODO(bmahler): Consider providing recovery mechanisms. |
| 2944 | try { |
| 2945 | process->initialize(); |
| 2946 | } catch (const std::exception& e) { |
| 2947 | LOG(FATAL) << "Aborting libprocess: '" << process->pid << "'" |
| 2948 | << " threw exception during initialization: " << e.what(); |
| 2949 | } catch (...) { |
| 2950 | LOG(FATAL) << "Aborting libprocess: '" << process->pid << "'" |
| 2951 | << " threw exception during initialization: unknown"; |
| 2952 | } |
| 2953 | |
| 2954 | state = ProcessBase::State::READY; |
| 2955 | process->state.store(state); |
| 2956 | } |
| 2957 | |
| 2958 | // We must hold a reference to the process because it's possible |
| 2959 | // that another worker races ahead and deletes the process after |
| 2960 | // we set the state to BLOCKED (see the comment below). |
| 2961 | ProcessReference reference = process->reference; |
| 2962 | |
| 2963 | while (!terminate && !blocked) { |
| 2964 | Event* event = nullptr; |
| 2965 | |
| 2966 | // NOTE: the event queue requires only a _single_ consumer at a |
| 2967 | // time ... this is where we act as that single consumer (and down |
| 2968 | // in `ProcessManager::cleanup` which we call from here). |
| 2969 | |
| 2970 | if (!process->events->consumer.empty()) { |
| 2971 | event = process->events->consumer.dequeue(); |
| 2972 | } else { |
| 2973 | // We now transition the process to BLOCKED. It's possible that |
| 2974 | // events get enqueued while we're still in the READY state. |
| 2975 | // If this happens, the process would not have been enqueued |
| 2976 | // into the run queue and we need to continue processing the |
| 2977 | // events! |
| 2978 | // |
| 2979 | // However, when checking for such events, we need to be |
| 2980 | // careful not to process the events if they were enqueued |
| 2981 | // *after* we transitioned to BLOCKED. In this case, the |
nothing calls this directly
no test coverage detected