
  -spec process_info(Pid, Item) -> InfoTuple | [] | undefined
                        when
                            Pid :: pid(),
                            Item :: process_info_item(),
                            InfoTuple :: process_info_result_item();
                    (Pid, ItemList) -> InfoTupleList | [] | undefined
                        when
                            Pid :: pid(),
                            ItemList :: [Item],
                            Item :: process_info_item(),
                            InfoTupleList :: [InfoTuple],
                            InfoTuple :: process_info_result_item().

  Types:
    -type max_heap_size() ::
          Size ::
              non_neg_integer() |
              #{size => non_neg_integer(),
                kill => boolean(),
                error_logger => boolean()}.
    -type message_queue_data() :: off_heap | on_heap.
    -type priority_level() :: low | normal | high | max.
    -type process_info_item() ::
          backtrace | binary | catchlevel | current_function |
          current_location | current_stacktrace | dictionary |
          error_handler | garbage_collection | garbage_collection_info |
          group_leader | heap_size | initial_call | links | last_calls |
          memory | message_queue_len | messages | min_heap_size |
          min_bin_vheap_size | monitored_by | monitors |
          message_queue_data | priority | reductions | registered_name |
          sequential_trace_token | stack_size | status | suspending |
          total_heap_size | trace | trap_exit.
    -type process_info_result_item() ::
          {backtrace, Bin :: binary()} |
          {binary,
           BinInfo ::
               [{non_neg_integer(),
                 non_neg_integer(),
                 non_neg_integer()}]} |
          {catchlevel, CatchLevel :: non_neg_integer()} |
          {current_function,
           {Module :: module(), Function :: atom(), Arity :: arity()} |
           undefined} |
          {current_location,
           {Module :: module(),
            Function :: atom(),
            Arity :: arity(),
            Location ::
                [{file, Filename :: string()} |
                 {line, Line :: pos_integer()}]}} |
          {current_stacktrace, Stack :: [stack_item()]} |
          {dictionary, Dictionary :: [{Key :: term(), Value :: term()}]} |
          {error_handler, Module :: module()} |
          {garbage_collection, GCInfo :: [{atom(), non_neg_integer()}]} |
          {garbage_collection_info,
           GCInfo :: [{atom(), non_neg_integer()}]} |
          {group_leader, GroupLeader :: pid()} |
          {heap_size, Size :: non_neg_integer()} |
          {initial_call, mfa()} |
          {links, PidsAndPorts :: [pid() | port()]} |
          {last_calls, false | (Calls :: [mfa()])} |
          {memory, Size :: non_neg_integer()} |
          {message_queue_len, MessageQueueLen :: non_neg_integer()} |
          {messages, MessageQueue :: [term()]} |
          {min_heap_size, MinHeapSize :: non_neg_integer()} |
          {min_bin_vheap_size, MinBinVHeapSize :: non_neg_integer()} |
          {max_heap_size, MaxHeapSize :: max_heap_size()} |
          {monitored_by,
           MonitoredBy :: [pid() | port() | nif_resource()]} |
          {monitors,
           Monitors ::
               [{process | port,
                 Pid ::
                     pid() |
                     port() |
                     {RegName :: atom(), Node :: node()}}]} |
          {message_queue_data, MQD :: message_queue_data()} |
          {priority, Level :: priority_level()} |
          {reductions, Number :: non_neg_integer()} |
          {registered_name, [] | (Atom :: atom())} |
          {sequential_trace_token,
           [] | (SequentialTraceToken :: term())} |
          {stack_size, Size :: non_neg_integer()} |
          {status,
           Status ::
               exiting | garbage_collecting | waiting | running |
               runnable | suspended} |
          {suspending,
           SuspendeeList ::
               [{Suspendee :: pid(),
                 ActiveSuspendCount :: non_neg_integer(),
                 OutstandingSuspendCount :: non_neg_integer()}]} |
          {total_heap_size, Size :: non_neg_integer()} |
          {trace, InternalTraceFlags :: non_neg_integer()} |
          {trap_exit, Boolean :: boolean()}.
    -type stack_item() ::
          {Module :: module(),
           Function :: atom(),
           Arity :: arity() | (Args :: [term()]),
           Location ::
               [{file, Filename :: string()} |
                {line, Line :: pos_integer()}]}.

  Returns information about the process identified by Pid, as
  specified by Item or ItemList. Returns undefined if the
  process is not alive.

  If the process is alive and a single Item is specified, the
  returned value is the corresponding InfoTuple, unless Item =:=
  registered_name and the process has no registered name. In this
  case, [] is returned. This strange behavior is because of
  historical reasons, and is kept for backward compatibility.

  If ItemList is specified, the result is InfoTupleList. The 
  InfoTuples in InfoTupleList are included with the corresponding 
  Items in the same order as the Items were included in ItemList.
  Valid Items can be included multiple times in ItemList.

  Getting process information follows the signal ordering guarantees
  described in the Processes Chapter in the Erlang Reference
  Manual.

  Note:
    If registered_name is part of ItemList and the process has
    no name registered, a {registered_name, []}, InfoTuple 
    will be included in the resulting InfoTupleList. This
    behavior is different when a single Item =:= registered_name
    is specified, and when process_info/1 is used.

  Valid InfoTuples with corresponding Items:

  {backtrace, Bin}:
    Binary Bin contains the same information as the output from 
    erlang:process_display(Pid, backtrace). Use binary_to_list/1
    to obtain the string of characters from the binary.

  {binary, BinInfo}:
    BinInfo is a list containing miscellaneous information about
    binaries on the heap of this process. This InfoTuple can be
    changed or removed without prior notice. In the current
    implementation BinInfo is a list of tuples. The tuples
    contain; BinaryId, BinarySize, BinaryRefcCount.

    Depending on the value of the message_queue_data process
    flag the message queue may be stored on the heap.

  {catchlevel, CatchLevel}:
    CatchLevel is the number of currently active catches in this
    process. This InfoTuple can be changed or removed without
    prior notice.

  {current_function, {Module, Function, Arity} | undefined}:
    Module, Function, Arity is the current function call of
    the process. The value undefined can be returned if the
    process is currently executing native compiled code.

  {current_location, {Module, Function, Arity, Location}}:
    Module, Function, Arity is the current function call of
    the process. Location is a list of two-tuples describing the
    location in the source code.

  {current_stacktrace, Stack}:
    Returns the current call stack back-trace (stacktrace) of
    the process. The stack has the same format as in the catch
    part of a try. See The call-stack back trace (stacktrace).
    The depth of the stacktrace is truncated according to the 
    backtrace_depth system flag setting.

  {dictionary, Dictionary}:
    Dictionary is the process dictionary.

  {error_handler, Module}:
    Module is the error handler module used by the process (for
    undefined function calls, for example).

  {garbage_collection, GCInfo}:
    GCInfo is a list containing miscellaneous information about
    garbage collection for this process. The content of GCInfo
    can be changed without prior notice.

  {garbage_collection_info, GCInfo}:
    GCInfo is a list containing miscellaneous detailed
    information about garbage collection for this process. The
    content of GCInfo can be changed without prior notice. For
    details about the meaning of each item, see gc_minor_start
    in erlang:trace/3.

  {group_leader, GroupLeader}:
    GroupLeader is the group leader for the I/O of the process.

  {heap_size, Size}:
    Size is the size in words of the youngest heap generation of
    the process. This generation includes the process stack. This
    information is highly implementation-dependent, and can change
    if the implementation changes.

  {initial_call, {Module, Function, Arity}}:
    Module, Function, Arity is the initial function call with
    which the process was spawned.

  {links, PidsAndPorts}:
    PidsAndPorts is a list of process identifiers and port
    identifiers, with processes or ports to which the process has
    a link.

  {last_calls, false|Calls}:
    The value is false if call saving is not active for the
    process (see process_flag/3). If call saving is active, a
    list is returned, in which the last element is the most recent
    called.

  {memory, Size}:
    Size is the size in bytes of the process. This includes call
    stack, heap, and internal structures.

  {message_queue_len, MessageQueueLen}:
    MessageQueueLen is the number of messages currently in the
    message queue of the process. This is the length of the list 
    MessageQueue returned as the information item messages (see
    below).

  {messages, MessageQueue}:
    MessageQueue is a list of the messages to the process, which
    have not yet been processed.

  {min_heap_size, MinHeapSize}:
    MinHeapSize is the minimum heap size for the process.

  {min_bin_vheap_size, MinBinVHeapSize}:
    MinBinVHeapSize is the minimum binary virtual heap size for
    the process.

  {monitored_by, MonitoredBy}:
    A list of identifiers for all the processes, ports and NIF
    resources, that are monitoring the process.

  {monitors, Monitors}:
    A list of monitors (started by monitor/2) that are active
    for the process. For a local process monitor or a remote
    process monitor by a process identifier, the list consists of:

    {process, Pid}:
      Process is monitored by pid.

    {process, {RegName, Node}}:
      Local or remote process is monitored by name.

    {port, PortId}:
      Local port is monitored by port id.

    {port, {RegName, Node}}:
      Local port is monitored by name. Please note, that remote
      port monitors are not supported, so Node will always be
      the local node name.

  {message_queue_data, MQD}:
    MQD is the current value of the message_queue_data process
    flag, which can be either off_heap or on_heap. For more
    information, see the documentation of 
    process_flag(message_queue_data, MQD).

  {priority, Level}:
    Level is the current priority level for the process. For more
    information on priorities, see process_flag(priority, Level).

  {reductions, Number}:
    Number is the number of reductions executed by the process.

  {registered_name, Atom}:
    Atom is the registered process name. If the process has no
    registered name, this tuple is not present in the list.

  {sequential_trace_token, [] | SequentialTraceToken}:
    SequentialTraceToken is the sequential trace token for the
    process. This InfoTuple can be changed or removed without
    prior notice.

  {stack_size, Size}:
    Size is the stack size, in words, of the process.

  {status, Status}:
    Status is the status of the process and is one of the
    following:

     • exiting

     • garbage_collecting

     • waiting (for a message)

     • running

     • runnable (ready to run, but another process is running)

     • suspended (suspended on a "busy" port or by the BIF 
       erlang:suspend_process/1,2)

  {suspending, SuspendeeList}:
    SuspendeeList is a list of {Suspendee, ActiveSuspendCount,
    OutstandingSuspendCount} tuples. Suspendee is the process
    identifier of a process that has been, or is to be, suspended
    by the process identified by Pid through the BIF 
    erlang:suspend_process/2 or erlang:suspend_process/1.

    ActiveSuspendCount is the number of times Suspendee has
    been suspended by Pid. OutstandingSuspendCount is the
    number of not yet completed suspend requests sent by Pid,
    that is:

     • If ActiveSuspendCount =/= 0, Suspendee is currently
       in the suspended state.

     • If OutstandingSuspendCount =/= 0, option asynchronous
       of erlang:suspend_process/2 has been used and the
       suspendee has not yet been suspended by Pid.

    Notice that ActiveSuspendCount and OutstandingSuspendCount
    are not the total suspend count on Suspendee, only the parts
    contributed by Pid.

  {total_heap_size, Size}:
    Size is the total size, in words, of all heap fragments of
    the process. This includes the process stack and any
    unreceived messages that are considered to be part of the
    heap.

  {trace, InternalTraceFlags}:
    InternalTraceFlags is an integer representing the internal
    trace flag for this process. This InfoTuple can be changed
    or removed without prior notice.

  {trap_exit, Boolean}:
    Boolean is true if the process is trapping exits, otherwise 
    false.

  Notice that not all implementations support all these Items.

  Failures:

  badarg:
    If Pid is not a local process.

  badarg:
    If Item is an invalid item.
