Вопрос:

Принятый сокет от задачи, терпящей неудачу в другом процессе

sockets elixir gen-tcp

50 просмотра

1 ответ

134 Репутация автора

Я пытаюсь протестировать некоторый код эликсира и натолкнулся на поведение gen_tcp, которое я не понимаю. Когда я генерирую gen_tcp.accept сокет, я могу «получить к нему доступ» в задаче, в которой я его создал, но не в другом. Я подумал, что это проблема «control_process», но даже когда я добавил, что любая попытка использовать: inet.getstat приводит к ошибке неверного аргумента. Эликсир утверждает, что он также закрыт, но для этого вопроса получить проще было. Смотри ниже:

defmodule ElixirQuestion do
  def serve_one_client(socket, pid) 
  do  
    {:ok, server_socket} = :gen_tcp.accept(socket)
    :ok = :gen_tcp.controlling_process(server_socket, pid)
    IO.inspect(:inet.getstat(server_socket))
    server_socket 
  end 
end

{:ok, socket} = :gen_tcp.listen(0, [:binary, 
                                      {:packet, :raw}, 
                                      {:active, false}])
{:ok, port_number} = :inet.port(socket)
server_task = Task.async(fn -> ElixirQuestion.serve_one_client(socket, self()) end)
{:ok, _client_socket} = :gen_tcp.connect('localhost', port_number, [active: false]) 
server_socket = Task.await(server_task)

IO.inspect(:inet.getstat(server_socket))

Ожидаемый результат

{:ok,
 [recv_oct: 0, recv_cnt: 0, recv_max: 0, recv_avg: 0, recv_dvi: 0, send_oct: 0,
  send_cnt: 0, send_max: 0, send_avg: 0, send_pend: 0]}
{:ok,
 [recv_oct: 0, recv_cnt: 0, recv_max: 0, recv_avg: 0, recv_dvi: 0, send_oct: 0,
  send_cnt: 0, send_max: 0, send_avg: 0, send_pend: 0]}

Полученный вывод

{:ok,
 [recv_oct: 0, recv_cnt: 0, recv_max: 0, recv_avg: 0, recv_dvi: 0, send_oct: 0,
  send_cnt: 0, send_max: 0, send_avg: 0, send_pend: 0]}
{:error, :einval}

Эликсир версия

Erlang/OTP 19 [erts-8.3.5.3] [source] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false]

Elixir 1.4.5
Автор: janders Источник Размещён: 08.11.2017 10:12

Ответы (1)


2 плюса

160931 Репутация автора

Решение

self()inside Task.asyncвернет PID Taskпроцесса. Так как здесь вам нужно значение родительского процесса, вам нужно сохранить это значение вне переданного fn, Task.asyncа затем использовать его внутри.

Изменение:

server_task = Task.async(fn -> ElixirQuestion.serve_one_client(socket, self()) end)

чтобы:

me = self()
server_task = Task.async(fn -> ElixirQuestion.serve_one_client(socket, me) end)

дает мне результат, который вы ожидаете:

{:ok,
 [recv_oct: 0, recv_cnt: 0, recv_max: 0, recv_avg: 0, recv_dvi: 0, send_oct: 0,
  send_cnt: 0, send_max: 0, send_avg: 0, send_pend: 0]}
{:ok,
 [recv_oct: 0, recv_cnt: 0, recv_max: 0, recv_avg: 0, recv_dvi: 0, send_oct: 0,
  send_cnt: 0, send_max: 0, send_avg: 0, send_pend: 0]}
Автор: Dogbert Размещён: 09.11.2017 01:51
Вопросы из категории :
32x32