| 3084 | |
| 3085 | |
| 3086 | void ProcessManager::cleanup(ProcessBase* process) |
| 3087 | { |
| 3088 | VLOG(3) << "Cleaning up " << process->pid; |
| 3089 | |
| 3090 | // Invariant today is that all processes must be initialized and |
| 3091 | // have their state transition to READY before being terminated. |
| 3092 | CHECK(process->state.load() == ProcessBase::State::READY); |
| 3093 | |
| 3094 | // First, set the terminating state so no more events will get |
| 3095 | // enqueued and then decomission the event queue which will also |
| 3096 | // delete all the pending events. We want to delete the events |
| 3097 | // before we hold `processes_mutex` because deleting an event could |
| 3098 | // cause code outside libprocess to get executed which might cause a |
| 3099 | // deadlock with `processes_mutex`. Also, deleting the events now |
| 3100 | // rather than later has the nice property of making sure that any |
| 3101 | // _new_ events that might have gotten enqueued _BACK_ onto this |
| 3102 | // process due to the deleting of the pending events will get |
| 3103 | // dropped since this process is now TERMINATING, which eliminates |
| 3104 | // the potential of these new events from getting enqueued onto a |
| 3105 | // _new_ process that gets spawned with the same PID. |
| 3106 | process->state.store(ProcessBase::State::TERMINATING); |
| 3107 | |
| 3108 | process->events->consumer.decomission(); |
| 3109 | |
| 3110 | // Remove help strings for all installed routes for this process. |
| 3111 | dispatch(help, &Help::remove, process->pid.id); |
| 3112 | |
| 3113 | // Possible gate non-libprocess threads are waiting at. |
| 3114 | std::shared_ptr<Gate> gate = process->gate; |
| 3115 | |
| 3116 | // Remove process. |
| 3117 | synchronized (processes_mutex) { |
| 3118 | // Reset the reference so that we don't keep giving out references |
| 3119 | // in `ProcessManager::use`. |
| 3120 | // |
| 3121 | // NOTE: this must be done from within the `processes_mutex` since |
| 3122 | // that is where we read it and this is considered a write. |
| 3123 | process->reference.reset(); |
| 3124 | |
| 3125 | // Wait for all process references to get cleaned up. |
| 3126 | CHECK_SOME(process->pid.reference); |
| 3127 | while (!process->pid.reference->expired()) { |
| 3128 | #if defined(__i386__) || defined(__x86_64__) |
| 3129 | asm ("pause"); |
| 3130 | #endif |
| 3131 | } |
| 3132 | |
| 3133 | processes.erase(process->pid.id); |
| 3134 | |
| 3135 | // Note that we don't remove the process from the clock during |
| 3136 | // cleanup, but rather the clock is reset for a process when it is |
| 3137 | // created (see ProcessBase::ProcessBase). We do this so that |
| 3138 | // `SocketManager::exited()` can access the current time of the |
| 3139 | // process to "order" exited events. TODO(benh): It might make |
| 3140 | // sense to consider storing the time of the process as a field of |
| 3141 | // the class instead. It probably also makes sense to pass the |
| 3142 | // time to `SocketManager::exited()` rather than expect it to call |
| 3143 | // into the clock. |
nothing calls this directly
no test coverage detected