this repo has no description
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add trap_exit flag

garrison d488e95b 0d7d821b

+62 -28
+45 -25
lib/trinity/scheduler.ex
··· 44 44 defstruct @enforce_keys 45 45 end 46 46 47 + defmodule ProcInfo do 48 + @type t :: %__MODULE__{ 49 + trap_exit: boolean, 50 + links: [pid], 51 + } 52 + defstruct [ 53 + trap_exit: false, 54 + links: [], 55 + ] 56 + end 57 + 47 58 defmacro simulation_key, do: :_trinity_simulation 48 59 defmacro sim_node_key, do: :_trinity_simulation_node 49 60 ··· 194 205 %Simulation{proc_links: proc_links} = get_sim() 195 206 from_pid = self() 196 207 197 - from_links = 208 + from_info = 198 209 case :ets.lookup(proc_links, from_pid) do 199 - [{^from_pid, links}] -> links 200 - _ -> [] 210 + [{^from_pid, info}] -> info 211 + _ -> %ProcInfo{} 201 212 end 202 213 203 - to_links = 214 + to_info = 204 215 case :ets.lookup(proc_links, to_pid) do 205 - [{^to_pid, links}] -> links 206 - _ -> [] 216 + [{^to_pid, info}] -> info 217 + _ -> %ProcInfo{} 207 218 end 208 219 209 - case to_pid in from_links do 220 + case to_pid in from_info.links do 210 221 false -> 211 - :ets.insert(proc_links, {from_pid, [to_pid | from_links]}) 212 - :ets.insert(proc_links, {to_pid, [from_pid | to_links]}) 222 + :ets.insert(proc_links, {from_pid, %{from_info | links: [to_pid | from_info.links]}}) 223 + :ets.insert(proc_links, {to_pid, %{to_info | links: [from_pid | to_info.links]}}) 213 224 _ -> :noop 214 225 end 215 226 ··· 235 246 end 236 247 237 248 def handle_down(pid, reason) do 249 + # Should always be converted to :killed by the time it reaches the supervisor 250 + assert reason != :kill 251 + 238 252 sim = get_sim() 239 253 destroy_or_message_linked(sim, pid, reason, MapSet.new([pid])) 254 + destroy_process(sim, pid) 240 255 :ok 241 256 end 242 257 243 258 defp destroy_or_message_linked(%Simulation{} = sim, for_pid, reason, visited) do 244 - linked = get_linked(sim.proc_links, for_pid) 245 - linked = Enum.reject(linked, &MapSet.member?(visited, &1)) 259 + linked = 260 + case :ets.lookup(sim.proc_links, for_pid) do 261 + [{_key, %ProcInfo{links: links}}] -> links 262 + [] -> [] 263 + end 264 + |> Enum.reject(&MapSet.member?(visited, &1)) 246 265 247 266 visited = Enum.reduce(linked, visited, fn p, visited -> MapSet.put(visited, p) end) 248 267 Enum.reduce(linked, visited, fn p, visited -> 249 268 visited = destroy_or_message_linked(sim, p, reason, visited) 250 - destroy_or_message(sim, p, reason) 269 + destroy_or_message(sim, p, for_pid, reason) 251 270 visited 252 271 end) 253 272 end 254 273 255 - defp destroy_or_message(%Simulation{} = sim, pid, reason) do 256 - # TODO: trap_exit 257 - trap_exit = false 274 + defp destroy_or_message(%Simulation{} = sim, pid, from_pid, reason) do 275 + trap_exit = 276 + case :ets.lookup(sim.proc_links, pid) do 277 + [{_key, %ProcInfo{trap_exit: trap_exit}}] -> trap_exit 278 + [] -> false 279 + end 280 + 258 281 case trap_exit do 282 + true -> 283 + send pid, {:EXIT, from_pid, reason} 284 + handle_sent(pid) 285 + 259 286 false -> 260 287 destroy_process(sim, pid) 261 288 ··· 264 291 receive do 265 292 {:EXIT, ^pid, _reason} -> :noop 266 293 end 267 - end 268 - end 269 - 270 - defp get_linked(proc_links, pid) do 271 - case :ets.lookup(proc_links, pid) do 272 - [{_pid, links}] -> links 273 - [] -> [] 274 294 end 275 295 end 276 296 ··· 395 415 396 416 defp destroy_links(proc_links, from_pid) do 397 417 case :ets.lookup(proc_links, from_pid) do 398 - [{^from_pid, from_links}] -> 418 + [{^from_pid, %ProcInfo{links: from_links}}] -> 399 419 # Remove `from_pid` from each of its links' links 400 420 Enum.each(from_links, fn to_pid -> 401 - [{^to_pid, to_links}] = :ets.lookup(proc_links, to_pid) 402 - :ets.insert(proc_links, {to_pid, List.delete(to_links, from_pid)}) 421 + [{^to_pid, %ProcInfo{} = to_info}] = :ets.lookup(proc_links, to_pid) 422 + :ets.insert(proc_links, {to_pid, %{to_info | links: List.delete(to_info.links, from_pid)}}) 403 423 end) 404 424 405 425 # Delete `from_pid`'s links entry
+17 -3
lib/trinity/sim_process.ex
··· 1 1 defmodule Trinity.SimProcess do 2 2 alias Trinity.Scheduler 3 - alias Trinity.Scheduler.Simulation 3 + alias Trinity.Scheduler.{Simulation, ProcInfo} 4 4 5 5 import Trinity.Scheduler, only: [simulation_key: 0, sim_node_key: 0] 6 6 ··· 55 55 def flag(flag, value) do 56 56 case get_sim() do 57 57 nil -> Process.flag(flag, value) 58 - # TODO 59 - _sim -> :noop 58 + _sim -> sim_flag(flag, value) 60 59 end 61 60 end 62 61 ··· 134 133 Scheduler.handle_send_after(dest, message, time) 135 134 # Real send_after returns a timer ref, but it's probably not worth the overhead 136 135 nil 136 + end 137 + 138 + defp sim_flag(:trap_exit = _flag, value) when is_boolean(value) do 139 + %{proc_links: proc_links} = get_sim() 140 + pid = self() 141 + 142 + %ProcInfo{} = info = 143 + case :ets.lookup(proc_links, pid) do 144 + [{_key, info}] -> info 145 + [] -> %ProcInfo{} 146 + end 147 + old_value = info.trap_exit 148 + 149 + :ets.insert(proc_links, {pid, %{info | trap_exit: value}}) 150 + old_value 137 151 end 138 152 139 153 defp sim_alias do