Skip to content

Improve error message when trying to link :manual output pad to :push input pad #1090

@kidq330

Description

@kidq330

While the docs discourage using :push input pads, in the rare case they are needed, it would help to have a better error message to understand the location of the problem in the pipeline quicker - example:

Mix.install( [ {:membrane_core, "~> 1.0"}, {:membrane_generator_plugin, ">= 0.0.0"}] )

defmodule MyFilter do
  use Membrane.Filter

  def_input_pad :input,
    accepted_format: _any,
    flow_control: :push

  def_output_pad :output,
    accepted_format: _any,
    flow_control: :manual, demand_unit: :buffers

  @impl true
  def handle_init(_ctx, _opts) do
    {[], %{}}
  end

  @impl true
  def handle_buffer(_pad, buffer, _ctx, state) do
    {[forward: buffer], state}
  end

end


defmodule MyPipeline do
  use Membrane.Pipeline

  @impl true
  def handle_init(_ctx, _opts) do
    {[spec:
        [
          # NOTE: `Membrane.SilenceGenerator`'s output pad has `flow_control: :manual`
          child(:silence, %Membrane.SilenceGenerator{
            duration: :infinity,
            stream_format: %Membrane.RawAudio{
              channels: 1,
              sample_rate: 16_000,
              sample_format: :s16le
            }
          })
          |> child(:filter, MyFilter)
          |> child(:fake_sink, Membrane.Fake.Sink)
        ]
    ], %{}}
  end
end

{:ok, _supervisor, _pipeline} = Membrane.Pipeline.start_link(MyPipeline, [])
Process.sleep(:infinity)

Error message:

11:37:45.026 [error] <0.167.0>/:filter Error occured in Membrane Element:
** (Membrane.LinkError) Cannot connect :manual output :output to push input :input
    (membrane_core 1.2.6) lib/membrane/core/child/pad_controller.ex:33: Membrane.Core.Child.PadController.validate_pads_flow_control_compability!/4
    (membrane_core 1.2.6) lib/membrane/core/element/pad_controller.ex:182: Membrane.Core.Element.PadController.do_handle_link/6
    (membrane_core 1.2.6) lib/membrane/core/element.ex:192: Membrane.Core.Element.do_handle_call/3
    (membrane_core 1.2.6) lib/membrane/core/element.ex:179: Membrane.Core.Element.handle_call/3
    (stdlib 7.2.1) gen_server.erl:2470: :gen_server.try_handle_call/4
    (stdlib 7.2.1) gen_server.erl:2499: :gen_server.handle_msg/3
    (stdlib 7.2.1) proc_lib.erl:333: :proc_lib.init_p_do_apply/3



11:37:45.026 [error] GenServer #PID<0.175.0> terminating
** (Membrane.LinkError) Cannot connect :manual output :output to push input :input
    (membrane_core 1.2.6) lib/membrane/core/child/pad_controller.ex:33: Membrane.Core.Child.PadController.validate_pads_flow_control_compability!/4
    (membrane_core 1.2.6) lib/membrane/core/element/pad_controller.ex:182: Membrane.Core.Element.PadController.do_handle_link/6
    (membrane_core 1.2.6) lib/membrane/core/element.ex:192: Membrane.Core.Element.do_handle_call/3
    (membrane_core 1.2.6) lib/membrane/core/element.ex:179: Membrane.Core.Element.handle_call/3
    (stdlib 7.2.1) gen_server.erl:2470: :gen_server.try_handle_call/4
    (stdlib 7.2.1) gen_server.erl:2499: :gen_server.handle_msg/3
    (stdlib 7.2.1) proc_lib.erl:333: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.172.0>): {Membrane.Core.Message, :handle_link, [:input, %Membrane.Core.Parent.Link.Endpoint{child: :filter, pad_spec: :input, pad_ref: :input, pid: #PID<0.175.0>, pad_props: %{options: [], target_queue_size: nil, min_demand_factor: nil, auto_demand_size: nil, toilet_capacity: nil, throttling_factor: nil}, pad_info: %{name: :input, options: [], flow_control: :push, direction: :input, accepted_formats_str: ["_any"], availability: :always}, child_spec_ref: #Reference<0.3220357644.3508011010.51619>}, %Membrane.Core.Parent.Link.Endpoint{child: :silence, pad_spec: :output, pad_ref: :output, pid: #PID<0.172.0>, pad_props: %{options: []}, pad_info: %{name: :output, options: [], flow_control: :manual, demand_unit: nil, direction: :output, accepted_formats_str: ["RawAudio"], availability: :always}, child_spec_ref: #Reference<0.3220357644.3508011010.51619>}, %{stream_format_validation_params: [], link_metadata: %{observability_data: %{path: ["<0.167.0>/", ":silence"], observer_dbg_process: nil}}, output_effective_flow_control: :pull, output_pad_info: %{name: :output, options: [], flow_control: :manual, demand_unit: nil, direction: :output, accepted_formats_str: ["RawAudio"], availability: :always}}], []}
State: %Membrane.Core.Element.State{module: MyFilter, name: :filter, parent_pid: #PID<0.167.0>, playback: :stopped, type: :filter, internal_state: %{}, pads_info: %{input: %{name: :input, options: [], flow_control: :push, direction: :input, accepted_formats_str: ["_any"], availability: :always}, output: %{name: :output, options: [], flow_control: :manual, demand_unit: :buffers, direction: :output, accepted_formats_str: ["_any"], availability: :always}}, synchronization: %{timers: %{}, clock: nil, stream_sync: :membrane_no_sync, parent_clock: #PID<0.170.0>, latency: 0}, delayed_demands: MapSet.new([]), effective_flow_control: :push, initialized?: true, terminating?: false, setup_incomplete_returned?: false, delay_demands?: false, popping_auto_flow_queue?: false, stalker: %Membrane.Core.Stalker{pid: #PID<0.168.0>, ets: #Reference<0.3220357644.3508142082.51566>}, resource_guard: #PID<0.176.0>, subprocess_supervisor: #PID<0.174.0>, handle_demand_loop_counter: 0, pads_to_snapshot: MapSet.new([]), playback_queue: [], diamond_detection_state: %Membrane.Core.Element.DiamondDetectionController.DiamondDatectionState{ref_to_path: %{}, trigger_refs: MapSet.new([]), postponed?: false}, pads_data: %{}, satisfied_auto_output_pads: MapSet.new([]), awaiting_auto_input_pads: MapSet.new([]), auto_input_pads: [], resume_delayed_demands_loop_in_mailbox?: false}
Client #PID<0.172.0> is alive

    (stdlib 7.2.1) gen.erl:262: :gen.do_call/4
    (elixir 1.19.5) lib/gen_server.ex:1139: GenServer.call/3
    (membrane_core 1.2.6) lib/membrane/core/message.ex:39: Membrane.Core.Message.call/5
    (membrane_core 1.2.6) lib/membrane/core/element/pad_controller.ex:85: Membrane.Core.Element.PadController.do_handle_link/6
    (membrane_core 1.2.6) lib/membrane/core/element.ex:192: Membrane.Core.Element.do_handle_call/3
    (membrane_core 1.2.6) lib/membrane/core/element.ex:179: Membrane.Core.Element.handle_call/3
    (stdlib 7.2.1) gen_server.erl:2470: :gen_server.try_handle_call/4
    (stdlib 7.2.1) gen_server.erl:2499: :gen_server.handle_msg/3

The error message notes :filter as one of the offending elements, but it would help if it also listed :silence as the upstream offender.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions