Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ddc554a7ef | ||
|
|
b6d27b5333 | ||
|
|
2e54537524 | ||
|
|
0d8fa1a0ff | ||
|
|
764d0c1008 | ||
|
|
5f86d6158b |
+1
-1
@@ -16,7 +16,7 @@ The Elixir codebase itself has been already fully formatted and all further cont
|
||||
|
||||
Supervisors in Elixir are responsible for starting, shutting down and restarting child process when things go wrong. Most of the interaction with supervisors happen with the Supervisor module and it contains three main strategies: `:one_for_one`, `:rest_for_one` and `:one_for_all`.
|
||||
|
||||
However, sometimes the children of a supervisor are not known upfront and are rather started dynamically. For example, if you are building a web server, you have each request beind handled by a separate supervised process. Those cases were handled in the Supervisor module under a special strategy called `:simple_one_for_one`.
|
||||
However, sometimes the children of a supervisor are not known upfront and are rather started dynamically. For example, if you are building a web server, you have each request being handled by a separate supervised process. Those cases were handled in the Supervisor module under a special strategy called `:simple_one_for_one`.
|
||||
|
||||
Unfortunately, this special strategy changed the semantics of the supervisor in regards to initialization and shutdown. Plus some APIs expected different inputs or would be completely unavailable depending on the supervision strategy.
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ defmodule Port do
|
||||
reimplementing core part of the Runtime System, such as the `:user` and
|
||||
`:shell` processes.
|
||||
|
||||
## Zombie processes
|
||||
## Zombie OS processes
|
||||
|
||||
A port can be closed via the `close/1` function or by sending a `{pid, :close}`
|
||||
message. However, if the VM crashes, a long-running program started by the port
|
||||
|
||||
@@ -14,7 +14,7 @@ defmodule Logger.Translator do
|
||||
* `min_level` - the current Logger level
|
||||
* `level` - the level of the message being translated
|
||||
* `kind` - if the message is a `:report` or `:format`
|
||||
* `message` - the message to format. If it is :report`, it is a tuple
|
||||
* `message` - the message to format. If it is `:report`, it is a tuple
|
||||
with `{report_type, report_data}`, if it is `:format`, it is a
|
||||
tuple with `{format_message, format_args}`.
|
||||
|
||||
@@ -331,6 +331,10 @@ defmodule Logger.Translator do
|
||||
["\nStart Module: ", inspect(mod) | child_debug(min_level, debug)]
|
||||
end
|
||||
|
||||
defp child_info(_min_level, _child) do
|
||||
[]
|
||||
end
|
||||
|
||||
defp child_debug(:debug, restart_type: restart, shutdown: shutdown, child_type: type) do
|
||||
["\nRestart: ", inspect(restart), "\nShutdown: ", inspect(shutdown)] ++
|
||||
["\nType: ", inspect(type)]
|
||||
|
||||
@@ -84,7 +84,13 @@ defmodule Mix.Compilers.Elixir do
|
||||
stale_local_deps = stale_local_deps(manifest, modified)
|
||||
|
||||
{modules, structs, changed} =
|
||||
update_stale_entries(all_modules, all_sources, removed ++ changed, stale_local_deps, %{})
|
||||
update_stale_entries(
|
||||
all_modules,
|
||||
all_sources,
|
||||
removed ++ changed,
|
||||
stale_local_deps,
|
||||
stale_local_deps
|
||||
)
|
||||
|
||||
stale = changed -- removed
|
||||
|
||||
|
||||
@@ -18,6 +18,18 @@ defmodule Mix.Tasks.Cmd do
|
||||
mix cmd --app app1 --app app2 echo pwd
|
||||
|
||||
Aborts when a command exits with a non-zero status.
|
||||
|
||||
## Zombie OS processes
|
||||
|
||||
Beware that the Erlang VM does not terminate child processes
|
||||
when it shuts down. Therefore, if you use `mix cmd` to start
|
||||
long running processes and then shutdown the VM, it is likely
|
||||
that those child processes won't be terminated with the VM.
|
||||
|
||||
A solution is to make sure the child processes listen to the
|
||||
stdndard input and terminate when standard input is closed.
|
||||
We discuss this topic at length in the "Zombie OS processes"
|
||||
of the `Port` module documentation.
|
||||
"""
|
||||
|
||||
def run(args) do
|
||||
|
||||
@@ -7,7 +7,7 @@ defmodule Mix.Tasks.Run do
|
||||
Starts and runs the current application.
|
||||
|
||||
`mix run` can be used to start the current application dependencies
|
||||
ant the application itself. For long running systems, this is typically
|
||||
and the application itself. For long running systems, this is typically
|
||||
done with the `--no-halt` option:
|
||||
|
||||
mix run --no-halt
|
||||
|
||||
@@ -326,7 +326,7 @@ defmodule Mix.UmbrellaTest do
|
||||
end
|
||||
end
|
||||
|
||||
test "recompiles after path dependency changes" do
|
||||
test "recompiles after runtime path dependency changes" do
|
||||
in_fixture("umbrella_dep/deps/umbrella/apps", fn ->
|
||||
Mix.Project.in_project(:bar, "bar", fn _ ->
|
||||
Mix.Task.run("compile", ["--verbose"])
|
||||
@@ -360,22 +360,51 @@ defmodule Mix.UmbrellaTest do
|
||||
# Noop for runtime dependencies
|
||||
mtime = File.stat!("_build/dev/lib/bar/.mix/compile.elixir").mtime
|
||||
ensure_touched("_build/dev/lib/foo/ebin/Elixir.Foo.beam", mtime)
|
||||
|
||||
mtime = File.stat!("_build/dev/lib/bar/.mix/compile.elixir").mtime
|
||||
ensure_touched("_build/dev/lib/foo/.mix/compile.elixir", mtime)
|
||||
|
||||
assert Mix.Tasks.Compile.Elixir.run(["--verbose"]) == {:noop, []}
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
test "recompiles after compile time path dependency changes" do
|
||||
in_fixture("umbrella_dep/deps/umbrella/apps", fn ->
|
||||
Mix.Project.in_project(:bar, "bar", fn _ ->
|
||||
Mix.Task.run("compile", ["--verbose"])
|
||||
|
||||
# Add compile time dependency
|
||||
File.write!("lib/bar.ex", "defmodule Bar, do: Foo.foo")
|
||||
|
||||
assert Mix.Tasks.Compile.Elixir.run(["--verbose"]) == {:ok, []}
|
||||
assert_receive {:mix_shell, :info, ["Compiled lib/bar.ex"]}
|
||||
|
||||
# Recompiles for compile time dependencies
|
||||
mtime = File.stat!("_build/dev/lib/bar/.mix/compile.elixir").mtime
|
||||
ensure_touched("_build/dev/lib/foo/ebin/Elixir.Foo.beam", mtime)
|
||||
ensure_touched("_build/dev/lib/foo/.mix/compile.elixir", mtime)
|
||||
|
||||
assert Mix.Tasks.Compile.Elixir.run(["--verbose"]) == {:ok, []}
|
||||
assert_receive {:mix_shell, :info, ["Compiled lib/bar.ex"]}
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
test "recompiles after struct path dependency changes" do
|
||||
in_fixture("umbrella_dep/deps/umbrella/apps", fn ->
|
||||
Mix.Project.in_project(:bar, "bar", fn _ ->
|
||||
File.write!("../foo/lib/foo.ex", "defmodule Foo, do: defstruct [:bar]")
|
||||
|
||||
Mix.Task.run("compile", ["--verbose"])
|
||||
|
||||
# Add struct dependency
|
||||
File.write!("lib/bar.ex", "defmodule Bar, do: %Foo{bar: true}")
|
||||
|
||||
assert Mix.Tasks.Compile.Elixir.run(["--verbose"]) == {:ok, []}
|
||||
assert_receive {:mix_shell, :info, ["Compiled lib/bar.ex"]}
|
||||
|
||||
# Recompiles for struct dependencies
|
||||
mtime = File.stat!("_build/dev/lib/bar/.mix/compile.elixir").mtime
|
||||
ensure_touched("_build/dev/lib/foo/ebin/Elixir.Foo.beam", mtime)
|
||||
ensure_touched("_build/dev/lib/foo/.mix/compile.elixir", mtime)
|
||||
|
||||
assert Mix.Tasks.Compile.Elixir.run(["--verbose"]) == {:ok, []}
|
||||
|
||||
Reference in New Issue
Block a user