aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/src')
-rw-r--r--lib/kernel/src/application.erl172
-rw-r--r--lib/kernel/src/auth.erl16
-rw-r--r--lib/kernel/src/disk_log.erl252
-rw-r--r--lib/kernel/src/disk_log.hrl24
-rw-r--r--lib/kernel/src/erl_boot_server.erl28
-rw-r--r--lib/kernel/src/erl_ddll.erl49
-rw-r--r--lib/kernel/src/error_handler.erl13
-rw-r--r--lib/kernel/src/error_logger.erl79
-rw-r--r--lib/kernel/src/file.erl375
-rw-r--r--lib/kernel/src/gen_sctp.erl148
-rw-r--r--lib/kernel/src/gen_tcp.erl82
-rw-r--r--lib/kernel/src/gen_udp.erl52
-rw-r--r--lib/kernel/src/global.erl92
-rw-r--r--lib/kernel/src/global_group.erl58
-rw-r--r--lib/kernel/src/global_search.erl5
-rw-r--r--lib/kernel/src/heart.erl10
-rw-r--r--lib/kernel/src/hipe_unified_loader.erl11
-rw-r--r--lib/kernel/src/inet.erl96
-rw-r--r--lib/kernel/src/inet_res.erl379
-rw-r--r--lib/kernel/src/inet_udp.erl6
-rw-r--r--lib/kernel/src/net_adm.erl41
-rw-r--r--lib/kernel/src/net_kernel.erl39
-rw-r--r--lib/kernel/src/os.erl23
-rw-r--r--lib/kernel/src/pg2.erl68
-rw-r--r--lib/kernel/src/rpc.erl192
-rw-r--r--lib/kernel/src/seq_trace.erl44
-rw-r--r--lib/kernel/src/wrap_log_reader.erl35
27 files changed, 1842 insertions, 547 deletions
diff --git a/lib/kernel/src/application.erl b/lib/kernel/src/application.erl
index 2a193affd4..fa3a4c3d36 100644
--- a/lib/kernel/src/application.erl
+++ b/lib/kernel/src/application.erl
@@ -32,20 +32,30 @@
%%%-----------------------------------------------------------------
+-type start_type() :: 'normal'
+ | {'takeover', Node :: node()}
+ | {'failover', Node :: node()}.
-type restart_type() :: 'permanent' | 'transient' | 'temporary'.
--type application_opt() :: {'description', string()}
- | {'vsn', string()}
- | {'id', string()}
- | {'modules', [atom() | {atom(), any()}]}
- | {'registered', [atom()]}
- | {'applications', [atom()]}
- | {'included_applications', [atom()]}
- | {'env', [{atom(), any()}]}
- | {'start_phases', [{atom(), any()}] | 'undefined'}
- | {'maxT', timeout()} % max timeout
- | {'maxP', integer() | 'infinity'} % max processes
- | {'mod', {atom(), any()}}.
--type application_spec() :: {'application', atom(), [application_opt()]}.
+-type application_opt() :: {'description', Description :: string()}
+ | {'vsn', Vsn :: string()}
+ | {'id', Id :: string()}
+ | {'modules', [(Module :: module()) |
+ {Module :: module(), Version :: term()}]}
+ | {'registered', Names :: [Name :: atom()]}
+ | {'applications', [Application :: atom()]}
+ | {'included_applications', [Application :: atom()]}
+ | {'env', [{Par :: atom(), Val :: term()}]}
+ | {'start_phases',
+ [{Phase :: atom(), PhaseArgs :: term()}] | 'undefined'}
+ | {'maxT', MaxT :: timeout()} % max timeout
+ | {'maxP',
+ MaxP :: pos_integer() | 'infinity'} % max processes
+ | {'mod', Start :: {Module :: module(), StartArgs :: term()}}.
+-type application_spec() :: {'application',
+ Application :: atom(),
+ AppSpecKeys :: [application_opt()]}.
+
+-type(tuple_of(_T) :: tuple()).
%%------------------------------------------------------------------
@@ -61,16 +71,29 @@ behaviour_info(_Other) ->
%%% application_master.
%%%-----------------------------------------------------------------
--spec load(Application :: atom() | application_spec()) ->
- 'ok' | {'error', term()}.
+-spec load(AppDescr) -> 'ok' | {'error', Reason} when
+ AppDescr :: Application | (AppSpec :: application_spec()),
+ Application :: atom(),
+ Reason :: term().
load(Application) ->
- load(Application, []).
-
--spec load(Application :: atom() | application_spec(),
- Distributed :: any()) -> 'ok' | {'error', term()}.
+ load1(Application, []).
+
+-spec load(AppDescr, Distributed) -> 'ok' | {'error', Reason} when
+ AppDescr :: Application | (AppSpec :: application_spec()),
+ Application :: atom(),
+ Distributed :: {Application,Nodes}
+ | {Application,Time,Nodes}
+ | 'default',
+ Nodes :: [node() | tuple_of(node())],
+ Time :: pos_integer(),
+ Reason :: term().
load(Application, DistNodes) ->
+ load1(Application, DistNodes).
+
+%% Workaround due to specs.
+load1(Application, DistNodes) ->
case application_controller:load_application(Application) of
ok when DistNodes =/= [] ->
AppName = get_appl_name(Application),
@@ -85,18 +108,24 @@ load(Application, DistNodes) ->
Else
end.
--spec unload(Application :: atom()) -> 'ok' | {'error', term()}.
+-spec unload(Application) -> 'ok' | {'error', Reason} when
+ Application :: atom(),
+ Reason :: term().
unload(Application) ->
application_controller:unload_application(Application).
--spec start(Application :: atom()) -> 'ok' | {'error', term()}.
+-spec start(Application) -> 'ok' | {'error', Reason} when
+ Application :: atom(),
+ Reason :: term().
start(Application) ->
start(Application, temporary).
--spec start(Application :: atom() | application_spec(),
- RestartType :: restart_type()) -> any().
+-spec start(Application, Type) -> 'ok' | {'error', Reason} when
+ Application :: atom(),
+ Type :: restart_type(),
+ Reason :: term().
start(Application, RestartType) ->
case load(Application) of
@@ -120,12 +149,18 @@ start_boot(Application) ->
start_boot(Application, RestartType) ->
application_controller:start_boot_application(Application, RestartType).
--spec takeover(Application :: atom(), RestartType :: restart_type()) -> any().
+-spec takeover(Application, Type) -> 'ok' | {'error', Reason} when
+ Application :: atom(),
+ Type :: restart_type(),
+ Reason :: term().
takeover(Application, RestartType) ->
dist_ac:takeover_application(Application, RestartType).
--spec permit(Application :: atom(), Bool :: boolean()) -> 'ok' | {'error', term()}.
+-spec permit(Application, Permission) -> 'ok' | {'error', Reason} when
+ Application :: atom(),
+ Permission :: boolean(),
+ Reason :: term().
permit(Application, Bool) ->
case Bool of
@@ -142,105 +177,146 @@ permit(Application, Bool) ->
LocalResult
end.
--spec stop(Application :: atom()) -> 'ok' | {'error', term()}.
+-spec stop(Application) -> 'ok' | {'error', Reason} when
+ Application :: atom(),
+ Reason :: term().
stop(Application) ->
application_controller:stop_application(Application).
--spec which_applications() -> [{atom(), string(), string()}].
+-spec which_applications() -> [{Application, Description, Vsn}] when
+ Application :: atom(),
+ Description :: string(),
+ Vsn :: string().
which_applications() ->
application_controller:which_applications().
--spec which_applications(timeout()) -> [{atom(), string(), string()}].
+-spec which_applications(Timeout) -> [{Application, Description, Vsn}] when
+ Timeout :: timeout(),
+ Application :: atom(),
+ Description :: string(),
+ Vsn :: string().
which_applications(infinity) ->
application_controller:which_applications(infinity);
which_applications(Timeout) when is_integer(Timeout), Timeout>=0 ->
application_controller:which_applications(Timeout).
--spec loaded_applications() -> [{atom(), string(), string()}].
+-spec loaded_applications() -> [{Application, Description, Vsn}] when
+ Application :: atom(),
+ Description :: string(),
+ Vsn :: string().
loaded_applications() ->
application_controller:loaded_applications().
--spec info() -> any().
+-spec info() -> term().
info() ->
application_controller:info().
--spec set_env(Application :: atom(), Key :: atom(), Value :: any()) -> 'ok'.
+-spec set_env(Application, Par, Val) -> 'ok' when
+ Application :: atom(),
+ Par :: atom(),
+ Val :: term().
set_env(Application, Key, Val) ->
application_controller:set_env(Application, Key, Val).
--spec set_env(Application :: atom(), Key :: atom(),
- Value :: any(), Timeout :: timeout()) -> 'ok'.
+-spec set_env(Application, Par, Val, Timeout) -> 'ok' when
+ Application :: atom(),
+ Par :: atom(),
+ Val :: term(),
+ Timeout :: timeout().
set_env(Application, Key, Val, infinity) ->
application_controller:set_env(Application, Key, Val, infinity);
set_env(Application, Key, Val, Timeout) when is_integer(Timeout), Timeout>=0 ->
application_controller:set_env(Application, Key, Val, Timeout).
--spec unset_env(atom(), atom()) -> 'ok'.
+-spec unset_env(Application, Par) -> 'ok' when
+ Application :: atom(),
+ Par :: atom().
unset_env(Application, Key) ->
application_controller:unset_env(Application, Key).
--spec unset_env(atom(), atom(), timeout()) -> 'ok'.
+-spec unset_env(Application, Par, Timeout) -> 'ok' when
+ Application :: atom(),
+ Par :: atom(),
+ Timeout :: timeout().
unset_env(Application, Key, infinity) ->
application_controller:unset_env(Application, Key, infinity);
unset_env(Application, Key, Timeout) when is_integer(Timeout), Timeout>=0 ->
application_controller:unset_env(Application, Key, Timeout).
--spec get_env(atom()) -> 'undefined' | {'ok', term()}.
+-spec get_env(Par) -> 'undefined' | {'ok', Val} when
+ Par :: atom(),
+ Val :: term().
get_env(Key) ->
application_controller:get_pid_env(group_leader(), Key).
--spec get_env(atom(), atom()) -> 'undefined' | {'ok', term()}.
+-spec get_env(Application, Par) -> 'undefined' | {'ok', Val} when
+ Application :: atom(),
+ Par :: atom(),
+ Val :: term().
get_env(Application, Key) ->
application_controller:get_env(Application, Key).
--spec get_all_env() -> [{atom(), any()}].
+-spec get_all_env() -> Env when
+ Env :: [{Par :: atom(), Val :: term()}].
get_all_env() ->
application_controller:get_pid_all_env(group_leader()).
--spec get_all_env(atom()) -> [{atom(), any()}].
+-spec get_all_env(Application) -> Env when
+ Application :: atom(),
+ Env :: [{Par :: atom(), Val :: term()}].
get_all_env(Application) ->
application_controller:get_all_env(Application).
--spec get_key(atom()) -> 'undefined' | {'ok', term()}.
+-spec get_key(Key) -> 'undefined' | {'ok', Val} when
+ Key :: atom(),
+ Val :: term().
get_key(Key) ->
application_controller:get_pid_key(group_leader(), Key).
--spec get_key(atom(), atom()) -> 'undefined' | {'ok', term()}.
+-spec get_key(Application, Key) -> 'undefined' | {'ok', Val} when
+ Application :: atom(),
+ Key :: atom(),
+ Val :: term().
get_key(Application, Key) ->
application_controller:get_key(Application, Key).
--spec get_all_key() -> 'undefined' | [] | {'ok', [{atom(),any()},...]}.
+-spec get_all_key() -> [] | {'ok', Keys} when
+ Keys :: [{Key :: atom(),Val :: term()},...].
get_all_key() ->
application_controller:get_pid_all_key(group_leader()).
--spec get_all_key(atom()) -> 'undefined' | {'ok', [{atom(),any()},...]}.
+-spec get_all_key(Application) -> 'undefined' | Keys when
+ Application :: atom(),
+ Keys :: {'ok', [{Key :: atom(),Val :: term()},...]}.
get_all_key(Application) ->
application_controller:get_all_key(Application).
--spec get_application() -> 'undefined' | {'ok', atom()}.
+-spec get_application() -> 'undefined' | {'ok', Application} when
+ Application :: atom().
get_application() ->
application_controller:get_application(group_leader()).
--spec get_application(Pid :: pid()) -> 'undefined' | {'ok', atom()}
- ; (Module :: atom()) -> 'undefined' | {'ok', atom()}.
+-spec get_application(PidOrModule) -> 'undefined' | {'ok', Application} when
+ PidOrModule :: (Pid :: pid()) | (Module :: module()),
+ Application :: atom().
get_application(Pid) when is_pid(Pid) ->
case process_info(Pid, group_leader) of
@@ -252,8 +328,8 @@ get_application(Pid) when is_pid(Pid) ->
get_application(Module) when is_atom(Module) ->
application_controller:get_application_module(Module).
--spec start_type() -> 'undefined' | 'local' | 'normal'
- | {'takeover', node()} | {'failover', node()}.
+-spec start_type() -> StartType | 'undefined' | 'local' when
+ StartType :: start_type().
start_type() ->
application_controller:start_type(group_leader()).
diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl
index 5c7fe2421d..25c88a4e1d 100644
--- a/lib/kernel/src/auth.erl
+++ b/lib/kernel/src/auth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -57,7 +57,8 @@ start_link() ->
%%--Deprecated interface------------------------------------------------
--spec is_auth(Node :: node()) -> 'yes' | 'no'.
+-spec is_auth(Node) -> 'yes' | 'no' when
+ Node :: Node :: node().
is_auth(Node) ->
case net_adm:ping(Node) of
@@ -65,12 +66,15 @@ is_auth(Node) ->
pang -> no
end.
--spec cookie() -> cookie().
+-spec cookie() -> Cookie when
+ Cookie :: cookie().
cookie() ->
get_cookie().
--spec cookie(Cookies :: [cookie(),...] | cookie()) -> 'true'.
+-spec cookie(TheCookie) -> 'true' when
+ TheCookie :: Cookie | [Cookie],
+ Cookie :: cookie().
cookie([Cookie]) ->
set_cookie(Cookie);
@@ -82,7 +86,9 @@ cookie(Cookie) ->
node_cookie([Node, Cookie]) ->
node_cookie(Node, Cookie).
--spec node_cookie(Node :: node(), Cookie :: cookie()) -> 'yes' | 'no'.
+-spec node_cookie(Node, Cookie) -> 'yes' | 'no' when
+ Node :: node(),
+ Cookie :: cookie().
node_cookie(Node, Cookie) ->
set_cookie(Node, Cookie),
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl
index 7f1b5f9ec6..9b8d2db437 100644
--- a/lib/kernel/src/disk_log.erl
+++ b/lib/kernel/src/disk_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -70,9 +70,10 @@
%%% Contract type specifications
%%%----------------------------------------------------------------------
+-opaque continuation() :: #continuation{}.
+
-type bytes() :: binary() | [byte()].
--type log() :: term(). % XXX: refine
-type file_error() :: term(). % XXX: refine
-type invalid_header() :: term(). % XXX: refine
@@ -87,27 +88,30 @@
-type open_error_rsn() :: 'no_such_log'
| {'badarg', term()}
- | {'size_mismatch', dlog_size(), dlog_size()}
- | {'arg_mismatch', dlog_optattr(), term(), term()}
- | {'name_already_open', log()}
- | {'open_read_write', log()}
- | {'open_read_only', log()}
- | {'need_repair', log()}
- | {'not_a_log_file', string()}
- | {'invalid_index_file', string()}
+ | {'size_mismatch', CurrentSize :: dlog_size(),
+ NewSize :: dlog_size()}
+ | {'arg_mismatch', OptionName :: dlog_optattr(),
+ CurrentValue :: term(), Value :: term()}
+ | {'name_already_open', Log :: log()}
+ | {'open_read_write', Log :: log()}
+ | {'open_read_only', Log :: log()}
+ | {'need_repair', Log :: log()}
+ | {'not_a_log_file', FileName :: file:filename()}
+ | {'invalid_index_file', FileName :: file:filename()}
| {'invalid_header', invalid_header()}
| {'file_error', file:filename(), file_error()}
- | {'node_already_open', log()}.
+ | {'node_already_open', Log :: log()}.
-type dist_error_rsn() :: 'nodedown' | open_error_rsn().
--type ret() :: {'ok', log()}
- | {'repaired', log(), {'recovered', non_neg_integer()},
- {'badbytes', non_neg_integer()}}.
+-type ret() :: {'ok', Log :: log()}
+ | {'repaired', Log :: log(),
+ {'recovered', Rec :: non_neg_integer()},
+ {'badbytes', Bad :: non_neg_integer()}}.
-type open_ret() :: ret() | {'error', open_error_rsn()}.
-type dist_open_ret() :: {[{node(), ret()}],
[{node(), {'error', dist_error_rsn()}}]}.
--type all_open_ret() :: open_ret() | dist_open_ret().
--spec open(Args :: dlog_options()) -> all_open_ret().
+-spec open(ArgL) -> open_ret() | dist_open_ret() when
+ ArgL :: dlog_options().
open(A) ->
disk_log_server:open(check_arg(A, #arg{options = A})).
@@ -116,40 +120,57 @@ open(A) ->
| {'full', log()} | {'invalid_header', invalid_header()}
| {'file_error', file:filename(), file_error()}.
--spec log(Log :: log(), Term :: term()) -> 'ok' | {'error', log_error_rsn()}.
+-spec log(Log, Term) -> ok | {error, Reason :: log_error_rsn()} when
+ Log :: log(),
+ Term :: term().
log(Log, Term) ->
req(Log, {log, term_to_binary(Term)}).
--spec blog(Log :: log(), Bytes :: bytes()) -> 'ok' | {'error', log_error_rsn()}.
+-spec blog(Log, Bytes) -> ok | {error, Reason :: log_error_rsn()} when
+ Log :: log(),
+ Bytes :: bytes().
blog(Log, Bytes) ->
req(Log, {blog, check_bytes(Bytes)}).
--spec log_terms(Log :: log(), Terms :: [term()]) -> 'ok' | {'error', term()}.
+-spec log_terms(Log, TermList) -> ok | {error, Resaon :: log_error_rsn()} when
+ Log :: log(),
+ TermList :: [term()].
log_terms(Log, Terms) ->
Bs = terms2bins(Terms),
req(Log, {log, Bs}).
--spec blog_terms(Log :: log(), Bytes :: [bytes()]) -> 'ok' | {'error', term()}.
+-spec blog_terms(Log, BytesList) ->
+ ok | {error, Reason :: log_error_rsn()} when
+ Log :: log(),
+ BytesList :: [bytes()].
blog_terms(Log, Bytess) ->
Bs = check_bytes_list(Bytess, Bytess),
req(Log, {blog, Bs}).
-type notify_ret() :: 'ok' | {'error', 'no_such_log'}.
--spec alog(Log :: log(), Term :: term()) -> notify_ret().
+-spec alog(Log, Term) -> notify_ret() when
+ Log :: log(),
+ Term :: term().
alog(Log, Term) ->
notify(Log, {alog, term_to_binary(Term)}).
--spec alog_terms(Log :: log(), Terms :: [term()]) -> notify_ret().
+-spec alog_terms(Log, TermList) -> notify_ret() when
+ Log :: log(),
+ TermList :: [term()].
alog_terms(Log, Terms) ->
Bs = terms2bins(Terms),
notify(Log, {alog, Bs}).
--spec balog(Log :: log(), Bytes :: bytes()) -> notify_ret().
+-spec balog(Log, Bytes) -> notify_ret() when
+ Log :: log(),
+ Bytes :: bytes().
balog(Log, Bytes) ->
notify(Log, {balog, check_bytes(Bytes)}).
--spec balog_terms(Log :: log(), Bytes :: [bytes()]) -> notify_ret().
+-spec balog_terms(Log, ByteList) -> notify_ret() when
+ Log :: log(),
+ ByteList :: [bytes()].
balog_terms(Log, Bytess) ->
Bs = check_bytes_list(Bytess, Bytess),
notify(Log, {balog, Bs}).
@@ -157,18 +178,22 @@ balog_terms(Log, Bytess) ->
-type close_error_rsn() ::'no_such_log' | 'nonode'
| {'file_error', file:filename(), file_error()}.
--spec close(Log :: log()) -> 'ok' | {'error', close_error_rsn()}.
+-spec close(Log) -> 'ok' | {'error', close_error_rsn()} when
+ Log :: log().
close(Log) ->
req(Log, close).
-type lclose_error_rsn() :: 'no_such_log'
| {'file_error', file:filename(), file_error()}.
--spec lclose(Log :: log()) -> 'ok' | {'error', lclose_error_rsn()}.
+-spec lclose(Log) -> 'ok' | {'error', lclose_error_rsn()} when
+ Log :: log().
lclose(Log) ->
lclose(Log, node()).
--spec lclose(Log :: log(), Node :: node()) -> 'ok' | {'error', lclose_error_rsn()}.
+-spec lclose(Log, Node) -> 'ok' | {'error', lclose_error_rsn()} when
+ Log :: log(),
+ Node :: node().
lclose(Log, Node) ->
lreq(Log, close, Node).
@@ -178,29 +203,49 @@ lclose(Log, Node) ->
| {'invalid_header', invalid_header()}
| {'file_error', file:filename(), file_error()}.
--spec truncate(Log :: log()) -> 'ok' | {'error', trunc_error_rsn()}.
+-spec truncate(Log) -> 'ok' | {'error', trunc_error_rsn()} when
+ Log :: log().
truncate(Log) ->
req(Log, {truncate, none, truncate, 1}).
--spec truncate(Log :: log(), Head :: term()) -> 'ok' | {'error', trunc_error_rsn()}.
+-spec truncate(Log, Head) -> 'ok' | {'error', trunc_error_rsn()} when
+ Log :: log(),
+ Head :: term().
truncate(Log, Head) ->
req(Log, {truncate, {ok, term_to_binary(Head)}, truncate, 2}).
--spec btruncate(Log :: log(), Head :: bytes()) -> 'ok' | {'error', trunc_error_rsn()}.
+-spec btruncate(Log, BHead) -> 'ok' | {'error', trunc_error_rsn()} when
+ Log :: log(),
+ BHead :: bytes().
btruncate(Log, Head) ->
req(Log, {truncate, {ok, check_bytes(Head)}, btruncate, 2}).
--spec reopen(Log :: log(), Filename :: file:filename()) -> 'ok' | {'error', term()}.
+-type reopen_error_rsn() :: no_such_log
+ | nonode
+ | {read_only_mode, log()}
+ | {blocked_log, log()}
+ | {same_file_name, log()} |
+ {invalid_index_file, file:filename()}
+ | {invalid_header, invalid_header()}
+ | {'file_error', file:filename(), file_error()}.
+
+-spec reopen(Log, File) -> 'ok' | {'error', reopen_error_rsn()} when
+ Log :: log(),
+ File :: file:filename().
reopen(Log, NewFile) ->
req(Log, {reopen, NewFile, none, reopen, 2}).
--spec reopen(Log :: log(), Filename :: file:filename(), Head :: term()) ->
- 'ok' | {'error', term()}.
+-spec reopen(Log, File, Head) -> 'ok' | {'error', reopen_error_rsn()} when
+ Log :: log(),
+ File :: file:filename(),
+ Head :: term().
reopen(Log, NewFile, NewHead) ->
req(Log, {reopen, NewFile, {ok, term_to_binary(NewHead)}, reopen, 3}).
--spec breopen(Log :: log(), Filename :: file:filename(), Head :: bytes()) ->
- 'ok' | {'error', term()}.
+-spec breopen(Log, File, BHead) -> 'ok' | {'error', reopen_error_rsn()} when
+ Log :: log(),
+ File :: file:filename(),
+ BHead :: bytes().
breopen(Log, NewFile, NewHead) ->
req(Log, {reopen, NewFile, {ok, check_bytes(NewHead)}, breopen, 3}).
@@ -210,21 +255,36 @@ breopen(Log, NewFile, NewHead) ->
| {'invalid_header', invalid_header()}
| {'file_error', file:filename(), file_error()}.
--spec inc_wrap_file(Log :: log()) -> 'ok' | {'error', inc_wrap_error_rsn()}.
+-spec inc_wrap_file(Log) -> 'ok' | {'error', inc_wrap_error_rsn()} when
+ Log :: log().
inc_wrap_file(Log) ->
req(Log, inc_wrap_file).
--spec change_size(Log :: log(), Size :: dlog_size()) -> 'ok' | {'error', term()}.
+-spec change_size(Log, Size) -> 'ok' | {'error', Reason} when
+ Log :: log(),
+ Size :: dlog_size(),
+ Reason :: no_such_log | nonode | {read_only_mode, Log}
+ | {blocked_log, Log}
+ | {new_size_too_small, CurrentSize :: pos_integer()}
+ | {badarg, size}
+ | {file_error, file:filename(), file_error()}.
change_size(Log, NewSize) ->
req(Log, {change_size, NewSize}).
--spec change_notify(Log :: log(), Pid :: pid(), Notify :: boolean()) ->
- 'ok' | {'error', term()}.
+-spec change_notify(Log, Owner, Notify) -> 'ok' | {'error', Reason} when
+ Log :: log(),
+ Owner :: pid(),
+ Notify :: boolean(),
+ Reason :: no_such_log | nonode | {blocked_log, Log}
+ | {badarg, notify} | {not_owner, Owner}.
change_notify(Log, Pid, NewNotify) ->
req(Log, {change_notify, Pid, NewNotify}).
--spec change_header(Log :: log(), Head :: {atom(), term()}) ->
- 'ok' | {'error', term()}.
+-spec change_header(Log, Header) -> 'ok' | {'error', Reason} when
+ Log :: log(),
+ Header :: {head, dlog_head_opt()} | {head_func, mfa()},
+ Reason :: no_such_log | nonode | {read_only_mode, Log}
+ | {blocked_log, Log} | {badarg, head}.
change_header(Log, NewHead) ->
req(Log, {change_header, NewHead}).
@@ -232,17 +292,21 @@ change_header(Log, NewHead) ->
| {'blocked_log', log()}
| {'file_error', file:filename(), file_error()}.
--spec sync(Log :: log()) -> 'ok' | {'error', sync_error_rsn()}.
+-spec sync(Log) -> 'ok' | {'error', sync_error_rsn()} when
+ Log :: log().
sync(Log) ->
req(Log, sync).
-type block_error_rsn() :: 'no_such_log' | 'nonode' | {'blocked_log', log()}.
--spec block(Log :: log()) -> 'ok' | {'error', block_error_rsn()}.
+-spec block(Log) -> 'ok' | {'error', block_error_rsn()} when
+ Log :: log().
block(Log) ->
block(Log, true).
--spec block(Log :: log(), QueueLogRecords :: boolean()) -> 'ok' | {'error', term()}.
+-spec block(Log, QueueLogRecords) -> 'ok' | {'error', block_error_rsn()} when
+ Log :: log(),
+ QueueLogRecords :: boolean().
block(Log, QueueLogRecords) ->
req(Log, {block, QueueLogRecords}).
@@ -250,19 +314,46 @@ block(Log, QueueLogRecords) ->
| {'not_blocked', log()}
| {'not_blocked_by_pid', log()}.
--spec unblock(Log :: log()) -> 'ok' | {'error', unblock_error_rsn()}.
+-spec unblock(Log) -> 'ok' | {'error', unblock_error_rsn()} when
+ Log :: log().
unblock(Log) ->
req(Log, unblock).
--spec format_error(Error :: term()) -> string().
+-spec format_error(Error) -> io_lib:chars() when
+ Error :: term().
format_error(Error) ->
do_format_error(Error).
--spec info(Log :: log()) -> [{atom(), any()}] | {'error', term()}.
+-type dlog_info() :: {name, Log :: log()}
+ | {file, File :: file:filename()}
+ | {type, Type :: dlog_type()}
+ | {format, Format :: dlog_format()}
+ | {size, Size :: dlog_size()}
+ | {mode, Mode :: dlog_mode()}
+ | {owners, [{pid(), Notify :: boolean()}]}
+ | {users, Users :: non_neg_integer()}
+ | {status, Status ::
+ ok | {blocked, QueueLogRecords :: boolean()}}
+ | {node, Node :: node()}
+ | {distributed, Dist :: local | [node()]}
+ | {head, Head :: none | {head, term()} | mfa()}
+ | {no_written_items, NoWrittenItems ::non_neg_integer()}
+ | {full, Full :: boolean}
+ | {no_current_bytes, non_neg_integer()}
+ | {no_current_items, non_neg_integer()}
+ | {no_items, non_neg_integer()}
+ | {current_file, pos_integer()}
+ | {no_overflows, {SinceLogWasOpened :: non_neg_integer(),
+ SinceLastInfo :: non_neg_integer()}}.
+-spec info(Log) -> InfoList | {'error', no_such_log} when
+ Log :: log(),
+ InfoList :: [dlog_info()].
info(Log) ->
sreq(Log, info).
--spec pid2name(Pid :: pid()) -> {'ok', log()} | 'undefined'.
+-spec pid2name(Pid) -> {'ok', Log} | 'undefined' when
+ Pid :: pid(),
+ Log :: log().
pid2name(Pid) ->
disk_log_server:start(),
case ets:lookup(?DISK_LOG_PID_TABLE, Pid) of
@@ -274,13 +365,31 @@ pid2name(Pid) ->
%% It retuns a {Cont2, ObjList} | eof | {error, Reason}
%% The initial continuation is the atom 'start'
--spec chunk(Log :: log(), Cont :: any()) ->
- {'error', term()} | 'eof' | {any(), [any()]} | {any(), [any()], integer()}.
+-type chunk_error_rsn() :: no_such_log
+ | {format_external, log()}
+ | {blocked_log, log()}
+ | {badarg, continuation}
+ | {not_internal_wrap, log()}
+ | {corrupt_log_file, FileName :: file:filename()}
+ | {file_error, file:filename(), file_error()}.
+
+-type chunk_ret() :: {Continuation2 :: continuation(), Terms :: [term()]}
+ | {Continuation2 :: continuation(),
+ Terms :: [term()],
+ Badbytes :: non_neg_integer()}
+ | eof
+ | {error, Reason :: chunk_error_rsn()}.
+
+-spec chunk(Log, Continuation) -> chunk_ret() when
+ Log :: log(),
+ Continuation :: start | continuation().
chunk(Log, Cont) ->
chunk(Log, Cont, infinity).
--spec chunk(Log :: log(), Cont :: any(), N :: pos_integer() | 'infinity') ->
- {'error', term()} | 'eof' | {any(), [any()]} | {any(), [any()], integer()}.
+-spec chunk(Log, Continuation, N) -> chunk_ret() when
+ Log :: log(),
+ Continuation :: start | continuation(),
+ N :: pos_integer() | infinity.
chunk(Log, Cont, infinity) ->
%% There cannot be more than ?MAX_CHUNK_SIZE terms in a chunk.
ichunk(Log, Cont, ?MAX_CHUNK_SIZE);
@@ -346,13 +455,24 @@ ichunk_bad_end([B | Bs], Mode, Log, C, Bad, A) ->
ichunk_bad_end(Bs, Mode, Log, C, Bad, [T | A])
end.
--spec bchunk(Log :: log(), Cont :: any()) ->
- {'error', any()} | 'eof' | {any(), [binary()]} | {any(), [binary()], integer()}.
+-type bchunk_ret() :: {Continuation2 :: continuation(),
+ Binaries :: [binary()]}
+ | {Continuation2 :: continuation(),
+ Binaries :: [binary()],
+ Badbytes :: non_neg_integer()}
+ | eof
+ | {error, Reason :: chunk_error_rsn()}.
+
+-spec bchunk(Log, Continuation) -> bchunk_ret() when
+ Log :: log(),
+ Continuation :: start | continuation().
bchunk(Log, Cont) ->
bchunk(Log, Cont, infinity).
--spec bchunk(Log :: log(), Cont :: any(), N :: 'infinity' | pos_integer()) ->
- {'error', any()} | 'eof' | {any(), [binary()]} | {any(), [binary()], integer()}.
+-spec bchunk(Log, Continuation, N) -> bchunk_ret() when
+ Log :: log(),
+ Continuation :: start | continuation(),
+ N :: pos_integer() | infinity.
bchunk(Log, Cont, infinity) ->
%% There cannot be more than ?MAX_CHUNK_SIZE terms in a chunk.
bichunk(Log, Cont, ?MAX_CHUNK_SIZE);
@@ -375,8 +495,14 @@ bichunk_end({C = #continuation{}, R, Bad}) ->
bichunk_end(R) ->
R.
--spec chunk_step(Log :: log(), Cont :: any(), N :: integer()) ->
- {'ok', any()} | {'error', term()}.
+-spec chunk_step(Log, Continuation, Step) ->
+ {'ok', any()} | {'error', Reason} when
+ Log :: log(),
+ Continuation :: start | continuation(),
+ Step :: integer(),
+ Reason :: no_such_log | end_of_log | {format_external, Log}
+ | {blocked_log, Log} | {badarg, continuation}
+ | {file_error, file:filename(), file_error()}.
chunk_step(Log, Cont, N) when is_integer(N) ->
ichunk_step(Log, Cont, N).
@@ -387,14 +513,18 @@ ichunk_step(_Log, More, N) when is_record(More, continuation) ->
ichunk_step(_Log, _, _) ->
{error, {badarg, continuation}}.
--spec chunk_info(More :: any()) ->
- [{'node', node()},...] | {'error', {'no_continuation', any()}}.
+-spec chunk_info(Continuation) -> InfoList | {error, Reason} when
+ Continuation :: continuation(),
+ InfoList :: [{node, Node :: node()}, ...],
+ Reason :: {no_continuation, Continuation}.
chunk_info(More = #continuation{}) ->
[{node, node(More#continuation.pid)}];
chunk_info(BadCont) ->
{error, {no_continuation, BadCont}}.
--spec accessible_logs() -> {[_], [_]}.
+-spec accessible_logs() -> {[LocalLog], [DistributedLog]} when
+ LocalLog :: log(),
+ DistributedLog :: log().
accessible_logs() ->
disk_log_server:accessible_logs().
diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl
index 9a94d4d3b9..259967650f 100644
--- a/lib/kernel/src/disk_log.hrl
+++ b/lib/kernel/src/disk_log.hrl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -53,18 +53,34 @@
%% Types -- alphabetically
%%------------------------------------------------------------------------
+-type dlog_byte() :: [dlog_byte()] | byte().
-type dlog_format() :: 'external' | 'internal'.
-type dlog_format_type() :: 'halt_ext' | 'halt_int' | 'wrap_ext' | 'wrap_int'.
-type dlog_head() :: 'none' | {'ok', binary()} | mfa().
+-type dlog_head_opt() :: none | term() | binary() | [dlog_byte()].
+-type log() :: term(). % XXX: refine
-type dlog_mode() :: 'read_only' | 'read_write'.
-type dlog_name() :: atom() | string().
-type dlog_optattr() :: 'name' | 'file' | 'linkto' | 'repair' | 'type'
| 'format' | 'size' | 'distributed' | 'notify'
| 'head' | 'head_func' | 'mode'.
--type dlog_options() :: [{dlog_optattr(), any()}].
+-type dlog_option() :: {name, Log :: log()}
+ | {file, FileName :: file:filename()}
+ | {linkto, LinkTo :: none | pid()}
+ | {repair, Repair :: true | false | truncate}
+ | {type, Type :: dlog_type}
+ | {format, Format :: dlog_format()}
+ | {size, Size :: dlog_size()}
+ | {distributed, Nodes :: [node()]}
+ | {notify, boolean()}
+ | {head, Head :: dlog_head_opt()}
+ | {head_func, mfa()}
+ | {mode, Mode :: dlog_mode()}.
+-type dlog_options() :: [dlog_option()].
-type dlog_repair() :: 'truncate' | boolean().
-type dlog_size() :: 'infinity' | pos_integer()
- | {pos_integer(), pos_integer()}.
+ | {MaxNoBytes :: pos_integer(),
+ MaxNoFiles :: pos_integer()}.
-type dlog_status() :: 'ok' | {'blocked', 'false' | [_]}. %QueueLogRecords
-type dlog_type() :: 'halt' | 'wrap'.
@@ -75,7 +91,7 @@
%% record of args for open
-record(arg, {name = 0,
version = undefined,
- file = none :: 'none' | string(),
+ file = none :: 'none' | file:filename(),
repair = true :: dlog_repair(),
size = infinity :: dlog_size(),
type = halt :: dlog_type(),
diff --git a/lib/kernel/src/erl_boot_server.erl b/lib/kernel/src/erl_boot_server.erl
index b4c5f5e27c..0d68d3e198 100644
--- a/lib/kernel/src/erl_boot_server.erl
+++ b/lib/kernel/src/erl_boot_server.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -59,7 +59,11 @@
-type ip4_address() :: {0..255,0..255,0..255,0..255}.
--spec start(Slaves :: [atom()]) -> {'ok', pid()} | {'error', any()}.
+-spec start(Slaves) -> {'ok', Pid} | {'error', What} when
+ Slaves :: [Host],
+ Host :: atom(),
+ Pid :: pid(),
+ What :: any().
start(Slaves) ->
case check_arg(Slaves) of
@@ -69,7 +73,11 @@ start(Slaves) ->
{error, {badarg, Slaves}}
end.
--spec start_link(Slaves :: [atom()]) -> {'ok', pid()} | {'error', any()}.
+-spec start_link(Slaves) -> {'ok', Pid} | {'error', What} when
+ Slaves :: [Host],
+ Host :: atom(),
+ Pid :: pid(),
+ What :: any().
start_link(Slaves) ->
case check_arg(Slaves) of
@@ -95,7 +103,10 @@ check_arg([], Result) ->
check_arg(_, _Result) ->
error.
--spec add_slave(Slave :: atom()) -> 'ok' | {'error', any()}.
+-spec add_slave(Slave) -> 'ok' | {'error', What} when
+ Slave :: Host,
+ Host :: atom(),
+ What :: any().
add_slave(Slave) ->
case inet:getaddr(Slave, inet) of
@@ -105,7 +116,10 @@ add_slave(Slave) ->
{error, {badarg, Slave}}
end.
--spec delete_slave(Slave :: atom()) -> 'ok' | {'error', any()}.
+-spec delete_slave(Slave) -> 'ok' | {'error', What} when
+ Slave :: Host,
+ Host :: atom(),
+ What :: any().
delete_slave(Slave) ->
case inet:getaddr(Slave, inet) of
@@ -131,7 +145,9 @@ add_subnet(Mask, Addr) when is_tuple(Mask), is_tuple(Addr) ->
delete_subnet(Mask, Addr) when is_tuple(Mask), is_tuple(Addr) ->
gen_server:call(boot_server, {delete, {Mask, Addr}}).
--spec which_slaves() -> [atom()].
+-spec which_slaves() -> Slaves when
+ Slaves :: [Host],
+ Host :: atom().
which_slaves() ->
gen_server:call(boot_server, which).
diff --git a/lib/kernel/src/erl_ddll.erl b/lib/kernel/src/erl_ddll.erl
index ce64589a29..646cac99c5 100644
--- a/lib/kernel/src/erl_ddll.erl
+++ b/lib/kernel/src/erl_ddll.erl
@@ -44,14 +44,18 @@ start() ->
stop() ->
ok.
--spec load_driver(Path :: path(), Driver :: driver()) ->
- 'ok' | {'error', any()}.
+-spec load_driver(Path, Name) -> 'ok' | {'error', ErrorDesc} when
+ Path :: path(),
+ Name :: driver(),
+ ErrorDesc :: term().
load_driver(Path, Driver) ->
do_load_driver(Path, Driver, [{driver_options,[kill_ports]}]).
--spec load(Path :: path(), Driver :: driver()) ->
- 'ok' | {'error', any()}.
+-spec load(Path, Name) -> 'ok' | {'error', ErrorDesc} when
+ Path :: path(),
+ Name :: driver(),
+ ErrorDesc ::term().
load(Path, Driver) ->
do_load_driver(Path, Driver, []).
@@ -100,30 +104,41 @@ do_unload_driver(Driver,Flags) ->
end
end.
--spec unload_driver(Driver :: driver()) -> 'ok' | {'error', any()}.
+-spec unload_driver(Name) -> 'ok' | {'error', ErrorDesc} when
+ Name :: driver(),
+ ErrorDesc :: term().
unload_driver(Driver) ->
do_unload_driver(Driver,[{monitor,pending_driver},kill_ports]).
--spec unload(Driver :: driver()) -> 'ok' | {'error', any()}.
+-spec unload(Name) -> 'ok' | {'error', ErrorDesc} when
+ Name :: driver(),
+ ErrorDesc :: term().
unload(Driver) ->
do_unload_driver(Driver,[]).
--spec reload(Path :: path(), Driver :: driver()) ->
- 'ok' | {'error', any()}.
+-spec reload(Path, Name) -> 'ok' | {'error', ErrorDesc} when
+ Path :: path(),
+ Name :: driver(),
+ ErrorDesc :: pending_process | OpaqueError,
+ OpaqueError :: term().
reload(Path,Driver) ->
do_load_driver(Path, Driver, [{reload,pending_driver}]).
--spec reload_driver(Path :: path(), Driver :: driver()) ->
- 'ok' | {'error', any()}.
+-spec reload_driver(Path, Name) -> 'ok' | {'error', ErrorDesc} when
+ Path :: path(),
+ Name :: driver(),
+ ErrorDesc :: pending_process | OpaqueError,
+ OpaqueError :: term().
reload_driver(Path,Driver) ->
do_load_driver(Path, Driver, [{reload,pending_driver},
{driver_options,[kill_ports]}]).
--spec format_error(Code :: atom()) -> string().
+-spec format_error(ErrorDesc) -> string() when
+ ErrorDesc :: term().
format_error(Code) ->
case Code of
@@ -135,7 +150,10 @@ format_error(Code) ->
erl_ddll:format_error_int(Code)
end.
--spec info(Driver :: driver()) -> [{atom(), any()}, ...].
+-spec info(Name) -> InfoList when
+ Name :: driver(),
+ InfoList :: [InfoItem, ...],
+ InfoItem :: {Tag :: atom(), Value :: term()}.
info(Driver) ->
[{processes, erl_ddll:info(Driver,processes)},
@@ -146,7 +164,12 @@ info(Driver) ->
{awaiting_load, erl_ddll:info(Driver,awaiting_load)},
{awaiting_unload, erl_ddll:info(Driver,awaiting_unload)}].
--spec info() -> [{string(), [{atom(), any()}]}].
+-spec info() -> AllInfoList when
+ AllInfoList :: [DriverInfo],
+ DriverInfo :: {DriverName, InfoList},
+ DriverName :: string(),
+ InfoList :: [InfoItem],
+ InfoItem :: {Tag :: atom(), Value :: term()}.
info() ->
{ok,DriverList} = erl_ddll:loaded_drivers(),
diff --git a/lib/kernel/src/error_handler.erl b/lib/kernel/src/error_handler.erl
index 6f69f4ccb9..e1f99bf417 100644
--- a/lib/kernel/src/error_handler.erl
+++ b/lib/kernel/src/error_handler.erl
@@ -28,8 +28,11 @@
-export([undefined_function/3, undefined_lambda/3, stub_function/3,
breakpoint/3]).
--spec undefined_function(Module :: atom(), Function :: atom(), Args :: [_]) ->
- any().
+-spec undefined_function(Module, Function, Args) ->
+ any() when
+ Module :: atom(),
+ Function :: atom(),
+ Args :: list().
undefined_function(Module, Func, Args) ->
case ensure_loaded(Module) of
@@ -51,8 +54,10 @@ undefined_function(Module, Func, Args) ->
crash(Module, Func, Args)
end.
--spec undefined_lambda(Module :: atom(), Function :: fun(), Args :: [_]) ->
- any().
+-spec undefined_lambda(Module, Fun, Args) -> term() when
+ Module :: atom(),
+ Fun :: fun(),
+ Args :: list().
undefined_lambda(Module, Fun, Args) ->
case ensure_loaded(Module) of
diff --git a/lib/kernel/src/error_logger.erl b/lib/kernel/src/error_logger.erl
index cafdc52e84..f94cca000f 100644
--- a/lib/kernel/src/error_logger.erl
+++ b/lib/kernel/src/error_logger.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -69,17 +69,22 @@ start_link() ->
%% Used for simple messages; error or information.
%%-----------------------------------------------------------------
--spec error_msg(Format :: string()) -> 'ok'.
+-spec error_msg(Format) -> 'ok' when
+ Format :: string().
error_msg(Format) ->
error_msg(Format,[]).
--spec error_msg(Format :: string(), Args :: list()) -> 'ok'.
+-spec error_msg(Format, Data) -> 'ok' when
+ Format :: string(),
+ Data :: list().
error_msg(Format, Args) ->
notify({error, group_leader(), {self(), Format, Args}}).
--spec format(Format :: string(), Args :: list()) -> 'ok'.
+-spec format(Format, Data) -> 'ok' when
+ Format :: string(),
+ Data :: list().
format(Format, Args) ->
notify({error, group_leader(), {self(), Format, Args}}).
@@ -90,12 +95,18 @@ format(Format, Args) ->
%% The 'std_error' error_report type can always be used.
%%-----------------------------------------------------------------
--spec error_report(Report :: any()) -> 'ok'.
+-type report() ::
+ [{Tag :: term(), Data :: term()} | term()] | string() | term().
+
+-spec error_report(Report) -> 'ok' when
+ Report :: report().
error_report(Report) ->
error_report(std_error, Report).
--spec error_report(Type :: any(), Report :: any()) -> 'ok'.
+-spec error_report(Type, Report) -> 'ok' when
+ Type :: term(),
+ Report :: report().
error_report(Type, Report) ->
notify({error_report, group_leader(), {self(), Type, Report}}).
@@ -109,12 +120,15 @@ error_report(Type, Report) ->
%% mapped to std_info or std_error accordingly.
%%-----------------------------------------------------------------
--spec warning_report(Report :: any()) -> 'ok'.
+-spec warning_report(Report) -> 'ok' when
+ Report :: report().
warning_report(Report) ->
warning_report(std_warning, Report).
--spec warning_report(Type :: any(), Report :: any()) -> 'ok'.
+-spec warning_report(Type, Report) -> 'ok' when
+ Type :: any(),
+ Report :: report().
warning_report(Type, Report) ->
{Tag, NType} = case error_logger:warning_map() of
@@ -143,12 +157,15 @@ warning_report(Type, Report) ->
%% other types of reports.
%%-----------------------------------------------------------------
--spec warning_msg(Format :: string()) -> 'ok'.
+-spec warning_msg(Format) -> 'ok' when
+ Format :: string().
warning_msg(Format) ->
warning_msg(Format,[]).
--spec warning_msg(Format :: string(), Args :: list()) -> 'ok'.
+-spec warning_msg(Format, Data) -> 'ok' when
+ Format :: string(),
+ Data :: list().
warning_msg(Format, Args) ->
Tag = case error_logger:warning_map() of
@@ -167,12 +184,15 @@ warning_msg(Format, Args) ->
%% The 'std_info' info_report type can always be used.
%%-----------------------------------------------------------------
--spec info_report(Report :: any()) -> 'ok'.
+-spec info_report(Report) -> 'ok' when
+ Report :: report().
info_report(Report) ->
info_report(std_info, Report).
--spec info_report(Type :: any(), Report :: any()) -> 'ok'.
+-spec info_report(Type, Report) -> 'ok' when
+ Type :: any(),
+ Report :: report().
info_report(Type, Report) ->
notify({info_report, group_leader(), {self(), Type, Report}}).
@@ -182,12 +202,15 @@ info_report(Type, Report) ->
%% information messages.
%%-----------------------------------------------------------------
--spec info_msg(Format :: string()) -> 'ok'.
+-spec info_msg(Format) -> 'ok' when
+ Format :: string().
info_msg(Format) ->
info_msg(Format,[]).
--spec info_msg(Format :: string(), Args :: list()) -> 'ok'.
+-spec info_msg(Format, Data) -> 'ok' when
+ Format :: string(),
+ Data :: list().
info_msg(Format, Args) ->
notify({info_msg, group_leader(), {self(), Format, Args}}).
@@ -223,17 +246,23 @@ swap_handler(silent) ->
swap_handler(false) ->
ok. % keep primitive event handler as-is
--spec add_report_handler(Module :: atom()) -> any().
+-spec add_report_handler(Handler) -> any() when
+ Handler :: module().
add_report_handler(Module) when is_atom(Module) ->
gen_event:add_handler(error_logger, Module, []).
--spec add_report_handler(atom(), any()) -> any().
+-spec add_report_handler(Handler, Args) -> Result when
+ Handler :: module(),
+ Args :: gen_event:handler_args(),
+ Result :: gen_event:add_handler_ret().
add_report_handler(Module, Args) when is_atom(Module) ->
gen_event:add_handler(error_logger, Module, Args).
--spec delete_report_handler(Module :: atom()) -> any().
+-spec delete_report_handler(Handler) -> Result when
+ Handler :: module(),
+ Result :: gen_event:del_handler_ret().
delete_report_handler(Module) when is_atom(Module) ->
gen_event:delete_handler(error_logger, Module, []).
@@ -250,9 +279,16 @@ simple_logger() ->
%% Log all errors to File for all eternity
--spec logfile(Request :: {'open', string()}) -> 'ok' | {'error',any()}
- ; (Request :: 'close') -> 'ok' | {'error', any()}
- ; (Request :: 'filename') -> atom() | string() | {'error', any()}.
+-type open_error() :: file:posix() | badarg | system_limit.
+
+-spec logfile(Request :: {open, Filename}) -> ok | {error, OpenReason} when
+ Filename ::file:name(),
+ OpenReason :: allready_have_logfile | open_error()
+ ; (Request :: close) -> ok | {error, CloseReason} when
+ CloseReason :: module_not_found
+ ; (Request :: filename) -> Filename | {error, FilenameReason} when
+ Filename :: file:name(),
+ FilenameReason :: no_log_file.
logfile({open, File}) ->
case lists:member(error_logger_file_h,
@@ -280,7 +316,8 @@ logfile(filename) ->
%% Possibly turn off all tty printouts, maybe we only want the errors
%% to go to a file
--spec tty(Flag :: boolean()) -> 'ok'.
+-spec tty(Flag) -> 'ok' when
+ Flag :: boolean().
tty(true) ->
Hs = gen_event:which_handlers(error_logger),
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index 88bcf9a9cc..f1a8aa9f77 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -79,15 +79,19 @@
-type file_info() :: #file_info{}.
-type fd() :: #file_descriptor{}.
-type io_device() :: pid() | fd().
--type location() :: integer() | {'bof', integer()} | {'cur', integer()}
- | {'eof', integer()} | 'bof' | 'cur' | 'eof'.
+-type location() :: integer() | {'bof', Offset :: integer()}
+ | {'cur', Offset :: integer()}
+ | {'eof', Offset :: integer()} | 'bof' | 'cur' | 'eof'.
-type mode() :: 'read' | 'write' | 'append'
| 'exclusive' | 'raw' | 'binary'
- | {'delayed_write', non_neg_integer(), non_neg_integer()}
- | 'delayed_write' | {'read_ahead', pos_integer()}
+ | {'delayed_write',
+ Size :: non_neg_integer(),
+ Delay :: non_neg_integer()}
+ | 'delayed_write' | {'read_ahead', Size :: pos_integer()}
| 'read_ahead' | 'compressed'
| {'encoding', unicode:encoding()}.
--type name() :: string() | atom() | [name()] | binary().
+-type deep_list() :: [char() | atom() | deep_list()].
+-type name() :: string() | atom() | deep_list() | (RawFilename :: binary()).
-type posix() :: 'eacces' | 'eagain' | 'ebadf' | 'ebusy' | 'edquot'
| 'eexist' | 'efault' | 'efbig' | 'eintr' | 'einval'
| 'eio' | 'eisdir' | 'eloop' | 'emfile' | 'emlink'
@@ -96,10 +100,14 @@
| 'enotblk' | 'enotdir' | 'enotsup' | 'enxio' | 'eperm'
| 'epipe' | 'erofs' | 'espipe' | 'esrch' | 'estale'
| 'exdev'.
--type bindings() :: any().
-
--type date() :: {pos_integer(), pos_integer(), pos_integer()}.
--type time() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}.
+-type bindings() :: erl_eval:binding_struct().
+
+-type date() :: {Year :: pos_integer(),
+ Month :: pos_integer(),
+ Day ::pos_integer()}.
+-type time() :: {Hour :: non_neg_integer(),
+ Minute :: non_neg_integer(),
+ Second :: non_neg_integer()}.
-type date_time() :: {date(), time()}.
-type posix_file_advise() :: 'normal' | 'sequential' | 'random'
| 'no_reuse' | 'will_need' | 'dont_need'.
@@ -107,8 +115,10 @@
%%%-----------------------------------------------------------------
%%% General functions
--spec format_error(Reason :: posix() | {integer(), atom(), any()}) ->
- string().
+-spec format_error(Reason) -> Chars when
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()},
+ Chars :: string().
format_error({_Line, ?MODULE, undefined_script}) ->
"no value returned from script";
@@ -129,7 +139,9 @@ format_error(terminated) ->
format_error(ErrorId) ->
erl_posix_msg:message(ErrorId).
--spec pid2name(Pid :: pid()) -> {'ok', filename()} | 'undefined'.
+-spec pid2name(Pid) -> {ok, Filename} | undefined when
+ Filename :: filename(),
+ Pid :: pid().
pid2name(Pid) when is_pid(Pid) ->
case whereis(?FILE_SERVER) of
@@ -148,42 +160,61 @@ pid2name(Pid) when is_pid(Pid) ->
%%% File server functions.
%%% Functions that do not operate on a single open file.
%%% Stateless.
--spec get_cwd() -> {'ok', filename()} | {'error', posix()}.
+-spec get_cwd() -> {ok, Dir} | {error, Reason} when
+ Dir :: filename(),
+ Reason :: posix().
get_cwd() ->
call(get_cwd, []).
--spec get_cwd(Drive :: string()) -> {'ok', filename()} | {'error', posix()}.
+-spec get_cwd(Drive) -> {ok, Dir} | {error, Reason} when
+ Drive :: string(),
+ Dir :: filename(),
+ Reason :: posix() | badarg.
get_cwd(Drive) ->
check_and_call(get_cwd, [file_name(Drive)]).
--spec set_cwd(Dirname :: name()) -> 'ok' | {'error', posix()}.
+-spec set_cwd(Dir) -> ok | {error, Reason} when
+ Dir :: name(),
+ Reason :: posix() | badarg.
set_cwd(Dirname) ->
check_and_call(set_cwd, [file_name(Dirname)]).
--spec delete(Name :: name()) -> 'ok' | {'error', posix()}.
+-spec delete(Filename) -> ok | {error, Reason} when
+ Filename :: name(),
+ Reason :: posix() | badarg.
delete(Name) ->
check_and_call(delete, [file_name(Name)]).
--spec rename(From :: name(), To :: name()) -> 'ok' | {'error', posix()}.
+-spec rename(Source, Destination) -> ok | {error, Reason} when
+ Source :: name(),
+ Destination :: name(),
+ Reason :: posix() | badarg.
rename(From, To) ->
check_and_call(rename, [file_name(From), file_name(To)]).
--spec make_dir(Name :: name()) -> 'ok' | {'error', posix()}.
+-spec make_dir(Dir) -> ok | {error, Reason} when
+ Dir :: name(),
+ Reason :: posix() | badarg.
make_dir(Name) ->
check_and_call(make_dir, [file_name(Name)]).
--spec del_dir(Name :: name()) -> 'ok' | {'error', posix()}.
+-spec del_dir(Dir) -> ok | {error, Reason} when
+ Dir :: name(),
+ Reason :: posix() | badarg.
del_dir(Name) ->
check_and_call(del_dir, [file_name(Name)]).
--spec read_file_info(Name :: name()) -> {'ok', file_info()} | {'error', posix()}.
+-spec read_file_info(Filename) -> {ok, FileInfo} | {error, Reason} when
+ Filename :: name(),
+ FileInfo :: file_info(),
+ Reason :: posix() | badarg.
read_file_info(Name) ->
check_and_call(read_file_info, [file_name(Name)]).
@@ -193,45 +224,66 @@ read_file_info(Name) ->
altname(Name) ->
check_and_call(altname, [file_name(Name)]).
--spec read_link_info(Name :: name()) -> {'ok', file_info()} | {'error', posix()}.
+-spec read_link_info(Name) -> {ok, FileInfo} | {error, Reason} when
+ Name :: name(),
+ FileInfo :: file_info(),
+ Reason :: posix() | badarg.
read_link_info(Name) ->
check_and_call(read_link_info, [file_name(Name)]).
--spec read_link(Name :: name()) -> {'ok', filename()} | {'error', posix()}.
+-spec read_link(Name) -> {ok, Filename} | {error, Reason} when
+ Name :: name(),
+ Filename :: filename(),
+ Reason :: posix() | badarg.
read_link(Name) ->
check_and_call(read_link, [file_name(Name)]).
--spec write_file_info(Name :: name(), Info :: file_info()) ->
- 'ok' | {'error', posix()}.
+-spec write_file_info(Filename, FileInfo) -> ok | {error, Reason} when
+ Filename :: name(),
+ FileInfo :: file_info(),
+ Reason :: posix() | badarg.
write_file_info(Name, Info = #file_info{}) ->
check_and_call(write_file_info, [file_name(Name), Info]).
--spec list_dir(Name :: name()) -> {'ok', [filename()]} | {'error', posix()}.
+-spec list_dir(Dir) -> {ok, Filenames} | {error, Reason} when
+ Dir :: name(),
+ Filenames :: [filename()],
+ Reason :: posix() | badarg.
list_dir(Name) ->
check_and_call(list_dir, [file_name(Name)]).
--spec read_file(Name :: name()) ->
- {'ok', binary()} | {'error', posix() | 'terminated' | 'system_limit'}.
+-spec read_file(Filename) -> {ok, Binary} | {error, Reason} when
+ Filename :: name(),
+ Binary :: binary(),
+ Reason :: posix() | badarg | terminated | system_limit.
read_file(Name) ->
check_and_call(read_file, [file_name(Name)]).
--spec make_link(Old :: name(), New :: name()) -> 'ok' | {'error', posix()}.
+-spec make_link(Existing, New) -> ok | {error, Reason} when
+ Existing :: name(),
+ New :: name(),
+ Reason :: posix() | badarg.
make_link(Old, New) ->
check_and_call(make_link, [file_name(Old), file_name(New)]).
--spec make_symlink(Old :: name(), New :: name()) -> 'ok' | {'error', posix()}.
+-spec make_symlink(Name1, Name2) -> ok | {error, Reason} when
+ Name1 :: name(),
+ Name2 :: name(),
+ Reason :: posix() | badarg.
make_symlink(Old, New) ->
check_and_call(make_symlink, [file_name(Old), file_name(New)]).
--spec write_file(Name :: name(), Bin :: iodata()) ->
- 'ok' | {'error', posix() | 'terminated' | 'system_limit'}.
+-spec write_file(Filename, Bytes) -> ok | {error, Reason} when
+ Filename :: name(),
+ Bytes :: iodata(),
+ Reason :: posix() | badarg | terminated | system_limit.
write_file(Name, Bin) ->
check_and_call(write_file, [file_name(Name), make_binary(Bin)]).
@@ -240,8 +292,11 @@ write_file(Name, Bin) ->
%% when it is time to change file server protocol again.
%% Meanwhile, it is implemented here, slightly less efficient.
--spec write_file(Name :: name(), Bin :: iodata(), Modes :: [mode()]) ->
- 'ok' | {'error', posix()}.
+-spec write_file(Filename, Bytes, Modes) -> ok | {error, Reason} when
+ Filename :: name(),
+ Bytes :: iodata(),
+ Modes :: [mode()],
+ Reason :: posix() | badarg | terminated | system_limit.
write_file(Name, Bin, ModeList) when is_list(ModeList) ->
case make_binary(Bin) of
@@ -295,8 +350,11 @@ raw_write_file_info(Name, #file_info{} = Info) ->
%% Contemporary mode specification - list of options
--spec open(Name :: name(), Modes :: [mode()]) ->
- {'ok', io_device()} | {'error', posix() | 'system_limit'}.
+-spec open(Filename, Modes) -> {ok, IoDevice} | {error, Reason} when
+ Filename :: name(),
+ Modes :: [mode()],
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | system_limit.
open(Item, ModeList) when is_list(ModeList) ->
case lists:member(raw, ModeList) of
@@ -349,7 +407,9 @@ open(Item, Mode) ->
%%% The File argument must be either a Pid or a handle
%%% returned from ?PRIM_FILE:open.
--spec close(File :: io_device()) -> 'ok' | {'error', posix() | 'terminated'}.
+-spec close(IoDevice) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | terminated.
close(File) when is_pid(File) ->
R = file_request(File, close),
@@ -367,9 +427,12 @@ close(#file_descriptor{module = Module} = Handle) ->
close(_) ->
{error, badarg}.
--spec advise(File :: io_device(), Offset :: integer(),
- Length :: integer(), Advise :: posix_file_advise()) ->
- 'ok' | {'error', posix()}.
+-spec advise(IoDevice, Offset, Length, Advise) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Offset :: integer(),
+ Length :: integer(),
+ Advise :: posix_file_advise(),
+ Reason :: posix() | badarg.
advise(File, Offset, Length, Advise) when is_pid(File) ->
R = file_request(File, {advise, Offset, Length, Advise}),
@@ -379,8 +442,11 @@ advise(#file_descriptor{module = Module} = Handle, Offset, Length, Advise) ->
advise(_, _, _, _) ->
{error, badarg}.
--spec read(File :: io_device() | atom(), Size :: non_neg_integer()) ->
- 'eof' | {'ok', [char()] | binary()} | {'error', posix()}.
+-spec read(IoDevice, Number) -> {ok, Data} | eof | {error, Reason} when
+ IoDevice :: io_device() | atom(),
+ Number :: non_neg_integer(),
+ Data :: string() | binary(),
+ Reason :: posix() | badarg | terminated.
read(File, Sz) when (is_pid(File) orelse is_atom(File)), is_integer(Sz), Sz >= 0 ->
case io:request(File, {get_chars, '', Sz}) of
@@ -395,8 +461,10 @@ read(#file_descriptor{module = Module} = Handle, Sz)
read(_, _) ->
{error, badarg}.
--spec read_line(File :: io_device() | atom()) ->
- 'eof' | {'ok', [char()] | binary()} | {'error', posix()}.
+-spec read_line(IoDevice) -> {ok, Data} | eof | {error, Reason} when
+ IoDevice :: io_device() | atom(),
+ Data :: string() | binary(),
+ Reason :: posix() | badarg | terminated.
read_line(File) when (is_pid(File) orelse is_atom(File)) ->
case io:request(File, {get_line, ''}) of
@@ -410,9 +478,12 @@ read_line(#file_descriptor{module = Module} = Handle) ->
read_line(_) ->
{error, badarg}.
--spec pread(File :: io_device(),
- LocationNumbers :: [{location(), non_neg_integer()}]) ->
- {'ok', [string() | binary() | 'eof']} | {'error', posix()}.
+-spec pread(IoDevice, LocNums) -> {ok, DataL} | eof | {error, Reason} when
+ IoDevice :: io_device(),
+ LocNums :: [{Location :: location(), Number :: non_neg_integer()}],
+ DataL :: [Data],
+ Data :: string() | binary() | eof,
+ Reason :: posix() | badarg | terminated.
pread(File, L) when is_pid(File), is_list(L) ->
pread_int(File, L, []);
@@ -435,10 +506,13 @@ pread_int(File, [{At, Sz} | T], R) when is_integer(Sz), Sz >= 0 ->
pread_int(_, _, _) ->
{error, badarg}.
--spec pread(File :: io_device(),
- Location :: location(),
- Size :: non_neg_integer()) ->
- 'eof' | {'ok', string() | binary()} | {'error', posix()}.
+-spec pread(IoDevice, Location, Number) ->
+ {ok, Data} | eof | {error, Reason} when
+ IoDevice :: io_device(),
+ Location :: location(),
+ Number :: non_neg_integer(),
+ Data :: string() | binary(),
+ Reason :: posix() | badarg | terminated.
pread(File, At, Sz) when is_pid(File), is_integer(Sz), Sz >= 0 ->
R = file_request(File, {pread, At, Sz}),
@@ -449,8 +523,10 @@ pread(#file_descriptor{module = Module} = Handle, Offs, Sz)
pread(_, _, _) ->
{error, badarg}.
--spec write(File :: io_device() | atom(), Byte :: iodata()) ->
- 'ok' | {'error', posix() | 'terminated'}.
+-spec write(IoDevice, Bytes) -> ok | {error, Reason} when
+ IoDevice :: io_device() | atom(),
+ Bytes :: iodata(),
+ Reason :: posix() | badarg | terminated.
write(File, Bytes) when (is_pid(File) orelse is_atom(File)) ->
case make_binary(Bytes) of
@@ -464,8 +540,11 @@ write(#file_descriptor{module = Module} = Handle, Bytes) ->
write(_, _) ->
{error, badarg}.
--spec pwrite(File :: io_device(), L :: [{location(), iodata()}]) ->
- 'ok' | {'error', {non_neg_integer(), posix()}}.
+-spec pwrite(IoDevice, LocBytes) -> ok | {error, {N, Reason}} when
+ IoDevice :: io_device(),
+ LocBytes :: [{Location :: location(), Bytes :: iodata()}],
+ N :: non_neg_integer(),
+ Reason :: posix() | badarg | terminated.
pwrite(File, L) when is_pid(File), is_list(L) ->
pwrite_int(File, L, 0);
@@ -486,10 +565,11 @@ pwrite_int(File, [{At, Bytes} | T], R) ->
pwrite_int(_, _, _) ->
{error, badarg}.
--spec pwrite(File :: io_device(),
- Location :: location(),
- Bytes :: iodata()) ->
- 'ok' | {'error', posix()}.
+-spec pwrite(IoDevice, Location, Bytes) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Location :: location(),
+ Bytes :: iodata(),
+ Reason :: posix() | badarg | terminated.
pwrite(File, At, Bytes) when is_pid(File) ->
R = file_request(File, {pwrite, At, Bytes}),
@@ -499,7 +579,9 @@ pwrite(#file_descriptor{module = Module} = Handle, Offs, Bytes) ->
pwrite(_, _, _) ->
{error, badarg}.
--spec datasync(File :: io_device()) -> 'ok' | {'error', posix()}.
+-spec datasync(IoDevice) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | terminated.
datasync(File) when is_pid(File) ->
R = file_request(File, datasync),
@@ -509,7 +591,9 @@ datasync(#file_descriptor{module = Module} = Handle) ->
datasync(_) ->
{error, badarg}.
--spec sync(File :: io_device()) -> 'ok' | {'error', posix()}.
+-spec sync(IoDevice) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | terminated.
sync(File) when is_pid(File) ->
R = file_request(File, sync),
@@ -519,8 +603,11 @@ sync(#file_descriptor{module = Module} = Handle) ->
sync(_) ->
{error, badarg}.
--spec position(File :: io_device(), Location :: location()) ->
- {'ok',integer()} | {'error', posix()}.
+-spec position(IoDevice, Location) -> {ok, NewPosition} | {error, Reason} when
+ IoDevice :: io_device(),
+ Location :: location(),
+ NewPosition :: integer(),
+ Reason :: posix() | badarg | terminated.
position(File, At) when is_pid(File) ->
R = file_request(File, {position,At}),
@@ -530,7 +617,9 @@ position(#file_descriptor{module = Module} = Handle, At) ->
position(_, _) ->
{error, badarg}.
--spec truncate(File :: io_device()) -> 'ok' | {'error', posix()}.
+-spec truncate(IoDevice) -> ok | {error, Reason} when
+ IoDevice :: io_device(),
+ Reason :: posix() | badarg | terminated.
truncate(File) when is_pid(File) ->
R = file_request(File, truncate),
@@ -540,17 +629,26 @@ truncate(#file_descriptor{module = Module} = Handle) ->
truncate(_) ->
{error, badarg}.
--spec copy(Source :: io_device() | name() | {name(), [mode()]},
- Destination :: io_device() | name() | {name(), [mode()]}) ->
- {'ok', non_neg_integer()} | {'error', posix()}.
+-spec copy(Source, Destination) -> {ok, BytesCopied} | {error, Reason} when
+ Source :: io_device() | Filename | {Filename, Modes},
+ Destination :: io_device() | Filename | {Filename, Modes},
+ Filename :: name(),
+ Modes :: [mode()],
+ BytesCopied :: non_neg_integer(),
+ Reason :: posix() | badarg | terminated.
copy(Source, Dest) ->
copy_int(Source, Dest, infinity).
--spec copy(Source :: io_device() | name() | {name(), [mode()]},
- Destination :: io_device() | name() | {name(), [mode()]},
- Length :: non_neg_integer() | 'infinity') ->
- {'ok', non_neg_integer()} | {'error', posix()}.
+-spec copy(Source, Destination, ByteCount) ->
+ {ok, BytesCopied} | {error, Reason} when
+ Source :: io_device() | Filename | {Filename, Modes},
+ Destination :: io_device() | Filename | {Filename, Modes},
+ Filename :: name(),
+ Modes :: [mode()],
+ ByteCount :: non_neg_integer() | infinity,
+ BytesCopied :: non_neg_integer(),
+ Reason :: posix() | badarg | terminated.
copy(Source, Dest, Length)
when is_integer(Length), Length >= 0;
@@ -772,8 +870,11 @@ ipread_s32bu_p32bu_2(File,
%%% The following functions, built upon the other interface functions,
%%% provide a higher-lever interface to files.
--spec consult(File :: name()) ->
- {'ok', list()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec consult(Filename) -> {ok, Terms} | {error, Reason} when
+ Filename :: name(),
+ Terms :: [term()],
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
consult(File) ->
case open(File, [read]) of
@@ -785,8 +886,14 @@ consult(File) ->
Error
end.
--spec path_consult(Paths :: [name()], File :: name()) ->
- {'ok', list(), filename()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec path_consult(Path, Filename) -> {ok, Terms, FullName} | {error, Reason} when
+ Path :: [Dir],
+ Dir :: name(),
+ Filename :: name(),
+ Terms :: [term()],
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_consult(Path, File) ->
case path_open(Path, File, [read]) of
@@ -803,13 +910,19 @@ path_consult(Path, File) ->
E2
end.
--spec eval(File :: name()) -> 'ok' | {'error', posix()}.
+-spec eval(Filename) -> ok | {error, Reason} when
+ Filename :: name(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
eval(File) ->
eval(File, erl_eval:new_bindings()).
--spec eval(File :: name(), Bindings :: bindings()) ->
- 'ok' | {'error', posix()}.
+-spec eval(Filename, Bindings) -> ok | {error, Reason} when
+ Filename :: name(),
+ Bindings :: bindings(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
eval(File, Bs) ->
case open(File, [read]) of
@@ -821,14 +934,24 @@ eval(File, Bs) ->
Error
end.
--spec path_eval(Paths :: [name()], File :: name()) ->
- {'ok', filename()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec path_eval(Path, Filename) -> {ok, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_eval(Path, File) ->
path_eval(Path, File, erl_eval:new_bindings()).
--spec path_eval(Paths :: [name()], File :: name(), Bindings :: bindings()) ->
- {'ok', filename()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec path_eval(Path, Filename, Bindings) ->
+ {ok, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ Bindings :: bindings(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_eval(Path, File, Bs) ->
case path_open(Path, File, [read]) of
@@ -845,14 +968,21 @@ path_eval(Path, File, Bs) ->
E2
end.
--spec script(File :: name()) ->
- {'ok', any()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec script(Filename) -> {ok, Value} | {error, Reason} when
+ Filename :: name(),
+ Value :: term(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
script(File) ->
script(File, erl_eval:new_bindings()).
--spec script(File :: name(), Bindings :: bindings()) ->
- {'ok', any()} | {'error', posix() | {integer(), atom(), any()}}.
+-spec script(Filename, Bindings) -> {ok, Value} | {error, Reason} when
+ Filename :: name(),
+ Bindings :: bindings(),
+ Value :: term(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
script(File, Bs) ->
case open(File, [read]) of
@@ -864,16 +994,27 @@ script(File, Bs) ->
Error
end.
--spec path_script/2 :: (Paths :: [name()], File :: name()) ->
- {'ok', term(), filename()} | {'error', posix() | {integer(), atom(), _}}.
+-spec path_script(Path, Filename) ->
+ {ok, Value, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ Value :: term(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_script(Path, File) ->
path_script(Path, File, erl_eval:new_bindings()).
--spec path_script(Paths :: [name()],
- File :: name(),
- Bindings :: bindings()) ->
- {'ok', term(), filename()} | {'error', posix() | {integer(), atom(), _}}.
+-spec path_script(Path, Filename, Bindings) ->
+ {ok, Value, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ Bindings :: bindings(),
+ Value :: term(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
path_script(Path, File, Bs) ->
case path_open(Path, File, [read]) of
@@ -898,8 +1039,14 @@ path_script(Path, File, Bs) ->
%% Searches the Paths for file Filename which can be opened with Mode.
%% The path list is ignored if Filename contains an absolute path.
--spec path_open(Paths :: [name()], Name :: name(), Modes :: [mode()]) ->
- {'ok', io_device(), filename()} | {'error', posix()}.
+-spec path_open(Path, Filename, Modes) ->
+ {ok, IoDevice, FullName} | {error, Reason} when
+ Path :: [Dir :: name()],
+ Filename :: name(),
+ Modes :: [mode()],
+ IoDevice :: io_device(),
+ FullName :: filename(),
+ Reason :: posix() | badarg | system_limit.
path_open(PathList, Name, Mode) ->
case file_name(Name) of
@@ -919,47 +1066,57 @@ path_open(PathList, Name, Mode) ->
end
end.
--spec change_mode(Name :: name(), Mode :: integer()) ->
- 'ok' | {'error', posix()}.
+-spec change_mode(Filename, Mode) -> ok | {error, Reason} when
+ Filename :: name(),
+ Mode :: integer(),
+ Reason :: posix() | badarg.
change_mode(Name, Mode)
when is_integer(Mode) ->
write_file_info(Name, #file_info{mode=Mode}).
--spec change_owner(Name :: name(), OwnerId :: integer()) ->
- 'ok' | {'error', posix()}.
+-spec change_owner(Filename, Uid) -> ok | {error, Reason} when
+ Filename :: name(),
+ Uid :: integer(),
+ Reason :: posix() | badarg.
change_owner(Name, OwnerId)
when is_integer(OwnerId) ->
write_file_info(Name, #file_info{uid=OwnerId}).
--spec change_owner(Name :: name(),
- OwnerId :: integer(),
- GroupId :: integer()) ->
- 'ok' | {'error', posix()}.
+-spec change_owner(Filename, Uid, Gid) -> ok | {error, Reason} when
+ Filename :: name(),
+ Uid :: integer(),
+ Gid :: integer(),
+ Reason :: posix() | badarg.
change_owner(Name, OwnerId, GroupId)
when is_integer(OwnerId), is_integer(GroupId) ->
write_file_info(Name, #file_info{uid=OwnerId, gid=GroupId}).
--spec change_group(Name :: name(), GroupId :: integer()) ->
- 'ok' | {'error', posix()}.
+-spec change_group(Filename, Gid) -> ok | {error, Reason} when
+ Filename :: name(),
+ Gid :: integer(),
+ Reason :: posix() | badarg.
change_group(Name, GroupId)
when is_integer(GroupId) ->
write_file_info(Name, #file_info{gid=GroupId}).
--spec change_time(Name :: name(), Time :: date_time()) ->
- 'ok' | {'error', posix()}.
+-spec change_time(Filename, Mtime) -> ok | {error, Reason} when
+ Filename :: name(),
+ Mtime :: date_time(),
+ Reason :: posix() | badarg.
change_time(Name, Time)
when is_tuple(Time) ->
write_file_info(Name, #file_info{mtime=Time}).
--spec change_time(Name :: name(),
- ATime :: date_time(),
- MTime :: date_time()) ->
- 'ok' | {'error', posix()}.
+-spec change_time(Filename, Atime, Mtime) -> ok | {error, Reason} when
+ Filename :: name(),
+ Atime :: date_time(),
+ Mtime :: date_time(),
+ Reason :: posix() | badarg.
change_time(Name, Atime, Mtime)
when is_tuple(Atime), is_tuple(Mtime) ->
diff --git a/lib/kernel/src/gen_sctp.erl b/lib/kernel/src/gen_sctp.erl
index cccfa75005..004f03f231 100644
--- a/lib/kernel/src/gen_sctp.erl
+++ b/lib/kernel/src/gen_sctp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2007-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -33,11 +33,57 @@
-export([error_string/1]).
-export([controlling_process/2]).
-
+-opaque assoc_id() :: term().
+-type hostname() :: inet:hostname().
+-type ip_address() :: inet:ip_address().
+-type port_number() :: 0..65535.
+-type posix() :: inet:posix().
+-type sctp_option() ::
+ {mode, list | binary} | list | binary
+ | {active, true | false | once}
+ | {buffer, non_neg_integer()}
+ | {tos, integer()}
+ | {priority, integer()}
+ | {dontroute, boolean()}
+ | {reuseaddr, boolean()}
+ | {linger, {boolean(), non_neg_integer()}}
+ | {sndbuf, non_neg_integer()}
+ | {recbuf, non_neg_integer()}
+ | {sctp_rtoinfo, #sctp_rtoinfo{}}
+ | {sctp_associnfo, #sctp_assocparams{}}
+ | {sctp_initmsg, #sctp_initmsg{}}
+ | {sctp_autoclose, timeout()}
+ | {sctp_nodelay, boolean()}
+ | {sctp_disable_fragments, boolean()}
+ | {sctp_i_want_mapped_v4_addr, boolean()}
+ | {sctp_maxseg, non_neg_integer()}
+ | {sctp_primary_addr, #sctp_prim{}}
+ | {sctp_set_peer_primary_addr, #sctp_setpeerprim{}}
+ | {sctp_adaptation_layer, #sctp_setadaptation{}}
+ | {sctp_peer_addr_params, #sctp_paddrparams{}}
+ | {sctp_default_send_param, #sctp_sndrcvinfo{}}
+ | {sctp_events, #sctp_event_subscribe{}}
+ | {sctp_delayed_ack_time, #sctp_assoc_value{}}
+ | {sctp_status, #sctp_status{}}
+ | {sctp_get_peer_addr_info, #sctp_paddrinfo{}}.
+-opaque sctp_socket() :: port().
+
+-spec open() -> {ok, Socket} | {error, posix()} when
+ Socket :: sctp_socket().
open() ->
open([]).
+-spec open(Port) -> {ok, Socket} | {error, posix()} when
+ Port :: port_number(),
+ Socket :: sctp_socket();
+ (Opts) -> {ok, Socket} | {error, posix()} when
+ Opts :: [Opt],
+ Opt :: {ip,IP} | {ifaddr,IP} | {port,Port} | sctp_option(),
+ IP :: ip_address() | any | loopback,
+ Port :: port_number(),
+ Socket :: sctp_socket().
+
open(Opts) when is_list(Opts) ->
Mod = mod(Opts, undefined),
case Mod:open(Opts) of
@@ -52,11 +98,21 @@ open(Port) when is_integer(Port) ->
open(X) ->
erlang:error(badarg, [X]).
+-spec open(Port, Opts) -> {ok, Socket} | {error, posix()} when
+ Opts :: [Opt],
+ Opt :: {ip,IP} | {ifaddr,IP} | {port,Port} | sctp_option(),
+ IP :: ip_address() | any | loopback,
+ Port :: port_number(),
+ Socket :: sctp_socket().
+
open(Port, Opts) when is_integer(Port), is_list(Opts) ->
open([{port,Port}|Opts]);
open(Port, Opts) ->
erlang:error(badarg, [Port,Opts]).
+-spec close(Socket) -> ok | {error, posix()} when
+ Socket :: sctp_socket().
+
close(S) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok,Mod} ->
@@ -68,6 +124,11 @@ close(S) ->
+-spec listen(Socket, IsServer) -> ok | {error, Reason} when
+ Socket :: sctp_socket(),
+ IsServer :: boolean(),
+ Reason :: term().
+
listen(S, Flag) when is_port(S), is_boolean(Flag) ->
case inet_db:lookup_socket(S) of
{ok,Mod} ->
@@ -77,9 +138,25 @@ listen(S, Flag) when is_port(S), is_boolean(Flag) ->
listen(S, Flag) ->
erlang:error(badarg, [S,Flag]).
+-spec connect(Socket, Addr, Port, Opts) -> {ok, Assoc} | {error, posix()} when
+ Socket :: sctp_socket(),
+ Addr :: ip_address() | hostname(),
+ Port :: port_number(),
+ Opts :: [Opt :: sctp_option()],
+ Assoc :: #sctp_assoc_change{}.
+
connect(S, Addr, Port, Opts) ->
connect(S, Addr, Port, Opts, infinity).
+-spec connect(Socket, Addr, Port, Opts, Timeout) ->
+ {ok, Assoc} | {error, posix()} when
+ Socket :: sctp_socket(),
+ Addr :: ip_address() | hostname(),
+ Port :: port_number(),
+ Opts :: [Opt :: sctp_option()],
+ Timeout :: timeout(),
+ Assoc :: #sctp_assoc_change{}.
+
connect(S, Addr, Port, Opts, Timeout) ->
case do_connect(S, Addr, Port, Opts, Timeout, true) of
badarg ->
@@ -88,9 +165,24 @@ connect(S, Addr, Port, Opts, Timeout) ->
Result
end.
+-spec connect_init(Socket, Addr, Port, Opts) ->
+ ok | {error, posix()} when
+ Socket :: sctp_socket(),
+ Addr :: ip_address() | hostname(),
+ Port :: port_number(),
+ Opts :: [sctp_option()].
+
connect_init(S, Addr, Port, Opts) ->
connect_init(S, Addr, Port, Opts, infinity).
+-spec connect_init(Socket, Addr, Port, Opts, Timeout) ->
+ ok | {error, posix()} when
+ Socket :: sctp_socket(),
+ Addr :: ip_address() | hostname(),
+ Port :: port_number(),
+ Opts :: [sctp_option()],
+ Timeout :: timeout().
+
connect_init(S, Addr, Port, Opts, Timeout) ->
case do_connect(S, Addr, Port, Opts, Timeout, false) of
badarg ->
@@ -130,12 +222,20 @@ do_connect(_S, _Addr, _Port, _Opts, _Timeout, _ConnWait) ->
badarg.
+-spec eof(Socket, Assoc) -> ok | {error, Reason} when
+ Socket :: sctp_socket(),
+ Assoc :: #sctp_assoc_change{},
+ Reason :: term().
eof(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) ->
eof_or_abort(S, AssocId, eof);
eof(S, Assoc) ->
erlang:error(badarg, [S,Assoc]).
+-spec abort(Socket, Assoc) -> ok | {error, posix()} when
+ Socket :: sctp_socket(),
+ Assoc :: #sctp_assoc_change{}.
+
abort(S, #sctp_assoc_change{assoc_id=AssocId}) when is_port(S) ->
eof_or_abort(S, AssocId, abort);
abort(S, Assoc) ->
@@ -151,6 +251,11 @@ eof_or_abort(S, AssocId, Action) ->
end.
+-spec send(Socket, SndRcvInfo, Data) -> ok | {error, Reason} when
+ Socket :: sctp_socket(),
+ SndRcvInfo :: #sctp_sndrcvinfo{},
+ Data :: binary | iolist(),
+ Reason :: term().
%% Full-featured send. Rarely needed.
send(S, #sctp_sndrcvinfo{}=SRI, Data) when is_port(S) ->
@@ -162,6 +267,13 @@ send(S, #sctp_sndrcvinfo{}=SRI, Data) when is_port(S) ->
send(S, SRI, Data) ->
erlang:error(badarg, [S,SRI,Data]).
+-spec send(Socket, Assoc, Stream, Data) -> ok | {error, Reason} when
+ Socket :: sctp_socket(),
+ Assoc :: #sctp_assoc_change{} | assoc_id(),
+ Stream :: integer(),
+ Data :: binary | iolist(),
+ Reason :: term().
+
send(S, #sctp_assoc_change{assoc_id=AssocId}, Stream, Data)
when is_port(S), is_integer(Stream) ->
case inet_db:lookup_socket(S) of
@@ -179,9 +291,36 @@ send(S, AssocId, Stream, Data)
send(S, AssocChange, Stream, Data) ->
erlang:error(badarg, [S,AssocChange,Stream,Data]).
+-spec recv(Socket) -> {ok, {FromIP, FromPort, AncData, Data}}
+ | {error, Reason} when
+ Socket :: sctp_socket(),
+ FromIP :: ip_address(),
+ FromPort :: port_number(),
+ AncData :: [#sctp_sndrcvinfo{}],
+ Data :: binary() | string() | #sctp_sndrcvinfo{}
+ | #sctp_assoc_change{} | #sctp_paddr_change{}
+ | #sctp_adaptation_event{},
+ Reason :: posix() | #sctp_send_failed{} | #sctp_paddr_change{}
+ | #sctp_pdapi_event{} | #sctp_remote_error{}
+ | #sctp_shutdown_event{}.
+
recv(S) ->
recv(S, infinity).
+-spec recv(Socket, Timeout) -> {ok, {FromIP, FromPort, AncData, Data}}
+ | {error, Reason} when
+ Socket :: sctp_socket(),
+ Timeout :: timeout(),
+ FromIP :: ip_address(),
+ FromPort :: port_number(),
+ AncData :: [#sctp_sndrcvinfo{}],
+ Data :: binary() | string() | #sctp_sndrcvinfo{}
+ | #sctp_assoc_change{} | #sctp_paddr_change{}
+ | #sctp_adaptation_event{},
+ Reason :: posix() | #sctp_send_failed{} | #sctp_paddr_change{}
+ | #sctp_pdapi_event{} | #sctp_remote_error{}
+ | #sctp_shutdown_event{}.
+
recv(S, Timeout) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok,Mod} ->
@@ -192,6 +331,8 @@ recv(S, Timeout) ->
erlang:error(badarg, [S,Timeout]).
+-spec error_string(ErrorNumber) -> ok | string() | unknown_error when
+ ErrorNumber :: integer().
error_string(0) ->
ok;
@@ -224,6 +365,9 @@ error_string(X) ->
erlang:error(badarg, [X]).
+-spec controlling_process(Socket, Pid) -> ok when
+ Socket :: sctp_socket(),
+ Pid :: pid().
controlling_process(S, Pid) when is_port(S), is_pid(Pid) ->
inet:udp_controlling_process(S, Pid);
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index 16a87d71b6..bee61ca84a 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -28,12 +28,35 @@
-include("inet_int.hrl").
+-type hostname() :: inet:hostname().
+-type ip_address() :: inet:ip_address().
+-type port_number() :: 0..65535.
+-type posix() :: inet:posix().
+-type socket() :: port().
+
%%
%% Connect a socket
%%
+
+-spec connect(Address, Port, Options) -> {ok, Socket} | {error, Reason} when
+ Address :: ip_address() | hostname(),
+ Port :: port_number(),
+ Options :: [Opt :: term()],
+ Socket :: socket(),
+ Reason :: posix().
+
connect(Address, Port, Opts) ->
connect(Address,Port,Opts,infinity).
+-spec connect(Address, Port, Options, Timeout) ->
+ {ok, Socket} | {error, Reason} when
+ Address :: ip_address() | hostname(),
+ Port :: port_number(),
+ Options :: [Opt :: term()],
+ Timeout :: timeout(),
+ Socket :: socket(),
+ Reason :: posix().
+
connect(Address, Port, Opts, Time) ->
Timer = inet:start_timer(Time),
Res = (catch connect1(Address,Port,Opts,Timer)),
@@ -72,6 +95,13 @@ try_connect([], _Port, _Opts, _Timer, _Mod, Err) ->
%%
%% Listen on a tcp port
%%
+
+-spec listen(Port, Options) -> {ok, ListenSocket} | {error, Reason} when
+ Port :: port_number(),
+ Options :: [Opt :: term()],
+ ListenSocket :: socket(),
+ Reason :: posix().
+
listen(Port, Opts) ->
Mod = mod(Opts, undefined),
case Mod:getserv(Port) of
@@ -85,6 +115,12 @@ listen(Port, Opts) ->
%%
%% Generic tcp accept
%%
+
+-spec accept(ListenSocket) -> {ok, Socket} | {error, Reason} when
+ ListenSocket :: socket(),
+ Socket :: socket(),
+ Reason :: closed | timeout | posix().
+
accept(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -93,6 +129,12 @@ accept(S) ->
Error
end.
+-spec accept(ListenSocket, Timeout) -> {ok, Socket} | {error, Reason} when
+ ListenSocket :: socket(),
+ Timeout :: timeout(),
+ Socket :: socket(),
+ Reason :: closed | timeout | posix().
+
accept(S, Time) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -104,6 +146,12 @@ accept(S, Time) when is_port(S) ->
%%
%% Generic tcp shutdown
%%
+
+-spec shutdown(Socket, How) -> ok | {error, Reason} when
+ Socket :: socket(),
+ How :: read | write | read_write,
+ Reason :: posix().
+
shutdown(S, How) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -115,12 +163,22 @@ shutdown(S, How) when is_port(S) ->
%%
%% Close
%%
+
+-spec close(Socket) -> ok when
+ Socket :: socket().
+
close(S) ->
inet:tcp_close(S).
%%
%% Send
%%
+
+-spec send(Socket, Packet) -> ok | {error, Reason} when
+ Socket :: socket(),
+ Packet :: string() | binary(),
+ Reason :: posix().
+
send(S, Packet) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -132,6 +190,14 @@ send(S, Packet) when is_port(S) ->
%%
%% Receive data from a socket (passive mode)
%%
+
+-spec recv(Socket, Length) -> {ok, Packet} | {error, Reason} when
+ Socket :: socket(),
+ Length :: non_neg_integer(),
+ Packet :: string() | binary() | HttpPacket,
+ Reason :: closed | posix(),
+ HttpPacket :: term().
+
recv(S, Length) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -140,6 +206,14 @@ recv(S, Length) when is_port(S) ->
Error
end.
+-spec recv(Socket, Length, Timeout) -> {ok, Packet} | {error, Reason} when
+ Socket :: socket(),
+ Length :: non_neg_integer(),
+ Timeout :: timeout(),
+ Packet :: string() | binary() | HttpPacket,
+ Reason :: closed | posix(),
+ HttpPacket :: term().
+
recv(S, Length, Time) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -159,6 +233,12 @@ unrecv(S, Data) when is_port(S) ->
%%
%% Set controlling process
%%
+
+-spec controlling_process(Socket, Pid) -> ok | {error, Reason} when
+ Socket :: socket(),
+ Pid :: pid(),
+ Reason :: closed | not_owner | posix().
+
controlling_process(S, NewOwner) ->
case inet_db:lookup_socket(S) of
{ok, _Mod} -> % Just check that this is an open socket
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 99020c7b6c..7d14615c04 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -25,17 +25,44 @@
-include("inet_int.hrl").
+-type hostname() :: inet:hostname().
+-type ip_address() :: inet:ip_address().
+-type port_number() :: 0..65535.
+-type posix() :: inet:posix().
+-type socket() :: port().
+
+-spec open(Port) -> {ok, Socket} | {error, Reason} when
+ Port :: port_number(),
+ Socket :: socket(),
+ Reason :: posix().
+
open(Port) ->
open(Port, []).
+-spec open(Port, Opts) -> {ok, Socket} | {error, Reason} when
+ Port :: port_number(),
+ Opts :: [Opt :: term()],
+ Socket :: socket(),
+ Reason :: posix().
+
open(Port, Opts) ->
Mod = mod(Opts, undefined),
{ok,UP} = Mod:getserv(Port),
Mod:open(UP, Opts).
+-spec close(Socket) -> ok when
+ Socket :: socket().
+
close(S) ->
inet:udp_close(S).
+-spec send(Socket, Address, Port, Packet) -> ok | {error, Reason} when
+ Socket :: socket(),
+ Address :: ip_address() | hostname(),
+ Port :: port_number(),
+ Packet :: string() | binary(),
+ Reason :: not_owner | posix().
+
send(S, Address, Port, Packet) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -61,6 +88,15 @@ send(S, Packet) when is_port(S) ->
Error
end.
+-spec recv(Socket, Length) ->
+ {ok, {Address, Port, Packet}} | {error, Reason} when
+ Socket :: socket(),
+ Length :: non_neg_integer(),
+ Address :: ip_address(),
+ Port :: port_number(),
+ Packet :: string() | binary(),
+ Reason :: not_owner | posix().
+
recv(S,Len) when is_port(S), is_integer(Len) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -69,6 +105,16 @@ recv(S,Len) when is_port(S), is_integer(Len) ->
Error
end.
+-spec recv(Socket, Length, Timeout) ->
+ {ok, {Address, Port, Packet}} | {error, Reason} when
+ Socket :: socket(),
+ Length :: non_neg_integer(),
+ Timeout :: timeout(),
+ Address :: ip_address(),
+ Port :: port_number(),
+ Packet :: string() | binary(),
+ Reason :: not_owner | posix().
+
recv(S,Len,Time) when is_port(S) ->
case inet_db:lookup_socket(S) of
{ok, Mod} ->
@@ -90,6 +136,10 @@ connect(S, Address, Port) when is_port(S) ->
Error
end.
+-spec controlling_process(Socket, Pid) -> ok when
+ Socket :: socket(),
+ Pid :: pid().
+
controlling_process(S, NewOwner) ->
inet:udp_controlling_process(S, NewOwner).
diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl
index 6343acd000..7d15f8bf83 100644
--- a/lib/kernel/src/global.erl
+++ b/lib/kernel/src/global.erl
@@ -166,7 +166,7 @@ start_link() ->
stop() ->
gen_server:call(global_name_server, stop, infinity).
--spec sync() -> 'ok' | {'error', term()}.
+-spec sync() -> 'ok' | {'error', Reason :: term()}.
sync() ->
case check_sync_nodes() of
{error, _} = Error ->
@@ -175,7 +175,7 @@ sync() ->
gen_server:call(global_name_server, {sync, SyncNodes}, infinity)
end.
--spec sync([node()]) -> 'ok' | {'error', term()}.
+-spec sync([node()]) -> 'ok' | {'error', Reason :: term()}.
sync(Nodes) ->
case check_sync_nodes(Nodes) of
{error, _} = Error ->
@@ -184,7 +184,10 @@ sync(Nodes) ->
gen_server:call(global_name_server, {sync, SyncNodes}, infinity)
end.
--spec send(term(), term()) -> pid().
+-spec send(Name, Msg) -> Pid when
+ Name :: term(),
+ Msg :: term(),
+ Pid :: pid().
send(Name, Msg) ->
case whereis_name(Name) of
Pid when is_pid(Pid) ->
@@ -195,7 +198,8 @@ send(Name, Msg) ->
end.
%% See OTP-3737.
--spec whereis_name(term()) -> pid() | 'undefined'.
+-spec whereis_name(Name) -> pid() | 'undefined' when
+ Name :: term().
whereis_name(Name) ->
where(Name).
@@ -219,13 +223,19 @@ node_disconnected(Node) ->
%% undefined which one of them is used.
%% Method blocks the name registration, but does not affect global locking.
%%-----------------------------------------------------------------
--spec register_name(term(), pid()) -> 'yes' | 'no'.
+-spec register_name(Name, Pid) -> 'yes' | 'no' when
+ Name :: term(),
+ Pid :: pid().
register_name(Name, Pid) when is_pid(Pid) ->
register_name(Name, Pid, fun random_exit_name/3).
--type method() :: fun((term(), pid(), pid()) -> pid() | 'none').
+-type method() :: fun((Name :: term(), Pid :: pid(), Pid2 :: pid()) ->
+ pid() | 'none').
--spec register_name(term(), pid(), method()) -> 'yes' | 'no'.
+-spec register_name(Name, Pid, Resolve) -> 'yes' | 'no' when
+ Name :: term(),
+ Pid :: pid(),
+ Resolve :: method().
register_name(Name, Pid, Method) when is_pid(Pid) ->
Fun = fun(Nodes) ->
case (where(Name) =:= undefined) andalso check_dupname(Name, Pid) of
@@ -257,7 +267,8 @@ check_dupname(Name, Pid) ->
end
end.
--spec unregister_name(term()) -> _.
+-spec unregister_name(Name) -> _ when
+ Name :: term().
unregister_name(Name) ->
case where(Name) of
undefined ->
@@ -273,11 +284,16 @@ unregister_name(Name) ->
gen_server:call(global_name_server, {registrar, Fun}, infinity)
end.
--spec re_register_name(term(), pid()) -> _.
+-spec re_register_name(Name, Pid) -> _ when
+ Name :: term(),
+ Pid :: pid().
re_register_name(Name, Pid) when is_pid(Pid) ->
re_register_name(Name, Pid, fun random_exit_name/3).
--spec re_register_name(term(), pid(), method()) -> _.
+-spec re_register_name(Name, Pid, Resolve) -> _ when
+ Name :: term(),
+ Pid :: pid(),
+ Resolve :: method().
re_register_name(Name, Pid, Method) when is_pid(Pid) ->
Fun = fun(Nodes) ->
gen_server:multi_call(Nodes,
@@ -288,7 +304,8 @@ re_register_name(Name, Pid, Method) when is_pid(Pid) ->
?trace({re_register_name, self(), Name, Pid, Method}),
gen_server:call(global_name_server, {registrar, Fun}, infinity).
--spec registered_names() -> [term()].
+-spec registered_names() -> [Name] when
+ Name :: term().
registered_names() ->
MS = ets:fun2ms(fun({Name,_Pid,_M,_RP,_R}) -> Name end),
ets:select(global_names, MS).
@@ -329,19 +346,25 @@ register_name_external(Name, Pid, Method) when is_pid(Pid) ->
unregister_name_external(Name) ->
unregister_name(Name).
--type id() :: {term(), term()}.
+-type id() :: {ResourceId :: term(), LockRequesterId :: term()}.
--spec set_lock(id()) -> boolean().
+-spec set_lock(Id) -> boolean() when
+ Id :: id().
set_lock(Id) ->
set_lock(Id, [node() | nodes()], infinity, 1).
-type retries() :: non_neg_integer() | 'infinity'.
--spec set_lock(id(), [node()]) -> boolean().
+-spec set_lock(Id, Nodes) -> boolean() when
+ Id :: id(),
+ Nodes :: [node()].
set_lock(Id, Nodes) ->
set_lock(Id, Nodes, infinity, 1).
--spec set_lock(id(), [node()], retries()) -> boolean().
+-spec set_lock(Id, Nodes, Retries) -> boolean() when
+ Id :: id(),
+ Nodes :: [node()],
+ Retries :: retries().
set_lock(Id, Nodes, Retries) when is_integer(Retries), Retries >= 0 ->
set_lock(Id, Nodes, Retries, 1);
set_lock(Id, Nodes, infinity) ->
@@ -363,11 +386,14 @@ set_lock({_ResourceId, _LockRequesterId} = Id, Nodes, Retries, Times) ->
set_lock(Id, Nodes, dec(Retries), Times+1)
end.
--spec del_lock(id()) -> 'true'.
+-spec del_lock(Id) -> 'true' when
+ Id :: id().
del_lock(Id) ->
del_lock(Id, [node() | nodes()]).
--spec del_lock(id(), [node()]) -> 'true'.
+-spec del_lock(Id, Nodes) -> 'true' when
+ Id :: id(),
+ Nodes :: [node()].
del_lock({_ResourceId, _LockRequesterId} = Id, Nodes) ->
?trace({del_lock, {me,self()}, Id, {nodes,Nodes}}),
gen_server:multi_call(Nodes, global_name_server, {del_lock, Id}),
@@ -375,13 +401,25 @@ del_lock({_ResourceId, _LockRequesterId} = Id, Nodes) ->
-type trans_fun() :: function() | {module(), atom()}.
--spec trans(id(), trans_fun()) -> term().
+-spec trans(Id, Fun) -> Res | aborted when
+ Id :: id(),
+ Fun :: trans_fun(),
+ Res :: term().
trans(Id, Fun) -> trans(Id, Fun, [node() | nodes()], infinity).
--spec trans(id(), trans_fun(), [node()]) -> term().
+-spec trans(Id, Fun, Nodes) -> Res | aborted when
+ Id :: id(),
+ Fun :: trans_fun(),
+ Nodes :: [node()],
+ Res :: term().
trans(Id, Fun, Nodes) -> trans(Id, Fun, Nodes, infinity).
--spec trans(id(), trans_fun(), [node()], retries()) -> term().
+-spec trans(Id, Fun, Nodes, Retries) -> Res | aborted when
+ Id :: id(),
+ Fun :: trans_fun(),
+ Nodes :: [node()],
+ Retries :: retries(),
+ Res :: term().
trans(Id, Fun, Nodes, Retries) ->
case set_lock(Id, Nodes, Retries) of
true ->
@@ -1928,7 +1966,10 @@ resolve_it(Method, Name, Pid1, Pid2) ->
minmax(P1,P2) ->
if node(P1) < node(P2) -> {P1, P2}; true -> {P2, P1} end.
--spec random_exit_name(term(), pid(), pid()) -> pid().
+-spec random_exit_name(Name, Pid1, Pid2) -> 'none' when
+ Name :: term(),
+ Pid1 :: pid(),
+ Pid2 :: pid().
random_exit_name(Name, Pid, Pid2) ->
{Min, Max} = minmax(Pid, Pid2),
error_logger:info_msg("global: Name conflict terminating ~w\n",
@@ -1936,12 +1977,19 @@ random_exit_name(Name, Pid, Pid2) ->
exit(Max, kill),
Min.
+-spec random_notify_name(Name, Pid1, Pid2) -> 'none' when
+ Name :: term(),
+ Pid1 :: pid(),
+ Pid2 :: pid().
random_notify_name(Name, Pid, Pid2) ->
{Min, Max} = minmax(Pid, Pid2),
Max ! {global_name_conflict, Name},
Min.
--spec notify_all_name(term(), pid(), pid()) -> 'none'.
+-spec notify_all_name(Name, Pid1, Pid2) -> 'none' when
+ Name :: term(),
+ Pid1 :: pid(),
+ Pid2 :: pid().
notify_all_name(Name, Pid, Pid2) ->
Pid ! {global_name_conflict, Name, Pid2},
Pid2 ! {global_name_conflict, Name, Pid},
diff --git a/lib/kernel/src/global_group.erl b/lib/kernel/src/global_group.erl
index 7e141ac5c7..025a9b8a5b 100644
--- a/lib/kernel/src/global_group.erl
+++ b/lib/kernel/src/global_group.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -62,9 +62,10 @@
-type sync_state() :: 'no_conf' | 'synced'.
-type group_name() :: atom().
--type group_tuple() :: {group_name(), [node()]}
- | {group_name(), publish_type(), [node()]}.
-
+-type group_tuple() :: {GroupName :: group_name(), [node()]}
+ | {GroupName :: group_name(),
+ PublishType :: publish_type(),
+ [node()]}.
%%%====================================================================================
%%% The state of the global_group process
@@ -97,11 +98,14 @@
%%% External exported
%%%====================================================================================
--spec global_groups() -> {group_name(), [group_name()]} | 'undefined'.
+-spec global_groups() -> {GroupName, GroupNames} | undefined when
+ GroupName :: group_name(),
+ GroupNames :: [GroupName].
global_groups() ->
request(global_groups).
--spec monitor_nodes(boolean()) -> 'ok'.
+-spec monitor_nodes(Flag) -> 'ok' when
+ Flag :: boolean().
monitor_nodes(Flag) ->
case Flag of
true -> request({monitor_nodes, Flag});
@@ -109,30 +113,41 @@ monitor_nodes(Flag) ->
_ -> {error, not_boolean}
end.
--spec own_nodes() -> [node()].
+-spec own_nodes() -> Nodes when
+ Nodes :: [Node :: node()].
own_nodes() ->
request(own_nodes).
-type name() :: atom().
-type where() :: {'node', node()} | {'group', group_name()}.
--spec registered_names(where()) -> [name()].
+-spec registered_names(Where) -> Names when
+ Where :: where(),
+ Names :: [Name :: name()].
registered_names(Arg) ->
request({registered_names, Arg}).
--spec send(name(), term()) -> pid() | {'badarg', {name(), term()}}.
+-spec send(Name, Msg) -> pid() | {'badarg', {Name, Msg}} when
+ Name :: name(),
+ Msg :: term().
send(Name, Msg) ->
request({send, Name, Msg}).
--spec send(where(), name(), term()) -> pid() | {'badarg', {name(), term()}}.
+-spec send(Where, Name, Msg) -> pid() | {'badarg', {Name, Msg}} when
+ Where :: where(),
+ Name :: name(),
+ Msg :: term().
send(Group, Name, Msg) ->
request({send, Group, Name, Msg}).
--spec whereis_name(name()) -> pid() | 'undefined'.
+-spec whereis_name(Name) -> pid() | 'undefined' when
+ Name :: name().
whereis_name(Name) ->
request({whereis_name, Name}).
--spec whereis_name(where(), name()) -> pid() | 'undefined'.
+-spec whereis_name(Where, Name) -> pid() | 'undefined' when
+ Where :: where(),
+ Name :: name().
whereis_name(Group, Name) ->
request({whereis_name, Group, Name}).
@@ -155,14 +170,14 @@ ng_add_check(Node, OthersNG) ->
ng_add_check(Node, PubType, OthersNG) ->
request({ng_add_check, Node, PubType, OthersNG}).
--type info_item() :: {'state', sync_state()}
- | {'own_group_name', group_name()}
- | {'own_group_nodes', [node()]}
- | {'synched_nodes', [node()]}
- | {'sync_error', [node()]}
- | {'no_contact', [node()]}
- | {'other_groups', [group_tuple()]}
- | {'monitoring', [pid()]}.
+-type info_item() :: {'state', State :: sync_state()}
+ | {'own_group_name', GroupName :: group_name()}
+ | {'own_group_nodes', Nodes :: [node()]}
+ | {'synched_nodes', Nodes :: [node()]}
+ | {'sync_error', Nodes :: [node()]}
+ | {'no_contact', Nodes :: [node()]}
+ | {'other_groups', Groups :: [group_tuple()]}
+ | {'monitoring', Pids :: [pid()]}.
-spec info() -> [info_item()].
info() ->
@@ -1012,6 +1027,7 @@ grp_tuple({Name, normal, Nodes}) ->
%%% The special process which checks that all nodes in the own global group
%%% agrees on the configuration.
%%%====================================================================================
+-spec sync_init(_, _, _, _) -> no_return().
sync_init(Type, Cname, PubType, Nodes) ->
{Up, Down} = sync_check_node(lists:delete(node(), Nodes), [], []),
sync_check_init(Type, Up, Cname, Nodes, Down, PubType).
@@ -1032,9 +1048,11 @@ sync_check_node([Node|Nodes], Up, Down) ->
%%% Check that all nodes are in agreement of the global
%%% group configuration.
%%%-------------------------------------------------------------
+-spec sync_check_init(_, _, _, _, _, _) -> no_return().
sync_check_init(Type, Up, Cname, Nodes, Down, PubType) ->
sync_check_init(Type, Up, Cname, Nodes, 3, [], Down, PubType).
+-spec sync_check_init(_, _, _, _, _, _, _, _) -> no_return().
sync_check_init(_Type, NoContact, _Cname, _Nodes, 0, ErrorNodes, Down, _PubType) ->
case ErrorNodes of
[] ->
diff --git a/lib/kernel/src/global_search.erl b/lib/kernel/src/global_search.erl
index b723e18a1b..0bf53e29b8 100644
--- a/lib/kernel/src/global_search.erl
+++ b/lib/kernel/src/global_search.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -69,6 +69,7 @@ start(Flag, Arg) ->
%%%====================================================================================
%%%====================================================================================
+-spec init_send(_) -> no_return().
init_send({any, NodesList, Name, Msg, From}) ->
case whereis_any_loop(NodesList, Name) of
undefined ->
@@ -115,6 +116,7 @@ init_send({node, Node, Name, Msg, From}) ->
%%%====================================================================================
%%%====================================================================================
+-spec init_whereis(_) -> no_return().
init_whereis({any, NodesList, Name, From}) ->
R = whereis_any_loop(NodesList, Name),
gen_server:cast(global_group, {find_name_res, R, self(), From}),
@@ -146,6 +148,7 @@ init_whereis({node, Node, Name, From}) ->
%%%====================================================================================
%%%====================================================================================
%%%====================================================================================
+-spec init_names(_) -> no_return().
init_names({group, Nodes, From}) ->
case names_group_loop(Nodes) of
group_down ->
diff --git a/lib/kernel/src/heart.erl b/lib/kernel/src/heart.erl
index e78acfc7a6..255ae4e51b 100644
--- a/lib/kernel/src/heart.erl
+++ b/lib/kernel/src/heart.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -85,19 +85,21 @@ init(Starter, Parent) ->
Starter ! {start_error, self()}
end.
--spec set_cmd(string()) -> 'ok' | {'error', {'bad_cmd', string()}}.
+-spec set_cmd(Cmd) -> 'ok' | {'error', {'bad_cmd', Cmd}} when
+ Cmd :: string().
set_cmd(Cmd) ->
heart ! {self(), set_cmd, Cmd},
wait().
--spec get_cmd() -> 'ok'.
+-spec get_cmd() -> {ok, Cmd} when
+ Cmd :: string().
get_cmd() ->
heart ! {self(), get_cmd},
wait().
--spec clear_cmd() -> {'ok', string()}.
+-spec clear_cmd() -> ok.
clear_cmd() ->
heart ! {self(), clear_cmd},
diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl
index f289b8110d..1d3eb926ca 100644
--- a/lib/kernel/src/hipe_unified_loader.erl
+++ b/lib/kernel/src/hipe_unified_loader.erl
@@ -258,7 +258,7 @@ find_callee_mfas(Patches) when is_list(Patches) ->
amd64 -> [];
arm -> find_callee_mfas(Patches, gb_sets:empty(), false);
powerpc -> find_callee_mfas(Patches, gb_sets:empty(), true);
- %% ppc64 -> find_callee_mfas(Patches, gb_sets:empty(), true);
+ ppc64 -> find_callee_mfas(Patches, gb_sets:empty(), true);
ultrasparc -> [];
x86 -> []
end.
@@ -301,6 +301,7 @@ mk_trampoline_map(CalleeMFAs, Trampolines) ->
SizeofLong =
case erlang:system_info(hipe_architecture) of
amd64 -> 8;
+ ppc64 -> 8;
_ -> 4
end,
mk_trampoline_map(tuple_size(CalleeMFAs), CalleeMFAs,
@@ -625,15 +626,15 @@ patch_instr(Address, Value, Type) ->
%%
%% XXX: It appears this is used for inserting both code addresses
%% and other data. In HiPE, code addresses are still 32-bit on
-%% 64-bit machines.
+%% some 64-bit machines.
write_word(DataAddress, DataWord) ->
case erlang:system_info(hipe_architecture) of
amd64 ->
hipe_bifs:write_u64(DataAddress, DataWord),
DataAddress+8;
- %% ppc64 ->
- %% hipe_bifs:write_u64(DataAddress, DataWord),
- %% DataAddress+8;
+ ppc64 ->
+ hipe_bifs:write_u64(DataAddress, DataWord),
+ DataAddress+8;
_ ->
hipe_bifs:write_u32(DataAddress, DataWord),
DataAddress+4
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 327e0f93f1..5649188c38 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -63,7 +63,8 @@
%% timer interface
-export([start_timer/1, timeout/1, timeout/2, stop_timer/1]).
--export_type([ip_address/0, socket/0]).
+-export_type([family_option/0, hostent/0, hostname/0, ip4_address/0,
+ ip6_address/0, ip_address/0, posix/0, socket/0]).
%% imports
-import(lists, [append/1, duplicate/2, filter/2, foldl/3]).
@@ -79,8 +80,16 @@
%%% ---------------------------------
%%% Contract type definitions
+
+-type hostent() :: #hostent{}.
+-type hostname() :: atom() | string().
+-type ip4_address() :: {0..255,0..255,0..255,0..255}.
+-type ip6_address() :: {0..65535,0..65535,0..65535,0..65535,
+ 0..65535,0..65535,0..65535,0..65535}.
+-type ip_address() :: ip4_address() | ip6_address().
+-type ip_port() :: 0..65535.
+-type posix() :: exbadport | exbadseq | file:posix().
-type socket() :: port().
--type posix() :: atom().
-type socket_setopt() ::
{'raw', non_neg_integer(), non_neg_integer(), binary()} |
@@ -106,7 +115,7 @@
{'packet',
0 | 1 | 2 | 4 | 'raw' | 'sunrm' | 'asn1' |
'cdr' | 'fcgi' | 'line' | 'tpkt' | 'http' | 'httph' | 'http_bin' | 'httph_bin' } |
- {'mode', list() | binary()} |
+ {'mode', 'list' | 'binary'} |
{'port', 'port', 'term'} |
{'exit_on_close', boolean()} |
{'low_watermark', non_neg_integer()} |
@@ -195,12 +204,13 @@
%%% ---------------------------------
--spec get_rc() -> [{any(),any()}].
+-spec get_rc() -> [{Par :: any(), Val :: any()}].
get_rc() ->
inet_db:get_rc().
--spec close(Socket :: socket()) -> 'ok'.
+-spec close(Socket) -> 'ok' when
+ Socket :: socket().
close(Socket) ->
prim_inet:close(Socket),
@@ -211,8 +221,10 @@ close(Socket) ->
ok
end.
--spec peername(Socket :: socket()) ->
- {'ok', {ip_address(), non_neg_integer()}} | {'error', posix()}.
+-spec peername(Socket) -> {ok, {Address, Port}} | {error, posix()} when
+ Socket :: socket(),
+ Address :: ip_address(),
+ Port :: non_neg_integer().
peername(Socket) ->
prim_inet:peername(Socket).
@@ -226,8 +238,10 @@ setpeername(Socket, undefined) ->
prim_inet:setpeername(Socket, undefined).
--spec sockname(Socket :: socket()) ->
- {'ok', {ip_address(), non_neg_integer()}} | {'error', posix()}.
+-spec sockname(Socket) -> {ok, {Address, Port}} | {error, posix()} when
+ Socket :: socket(),
+ Address :: ip_address(),
+ Port :: non_neg_integer().
sockname(Socket) ->
prim_inet:sockname(Socket).
@@ -260,8 +274,10 @@ send(Socket, Packet) ->
setopts(Socket, Opts) ->
prim_inet:setopts(Socket, Opts).
--spec getopts(Socket :: socket(), Opts :: [socket_getopt()]) ->
- {'ok', [socket_setopt()]} | {'error', posix()}.
+-spec getopts(Socket, Options) ->
+ {'ok', [socket_setopt()]} | {'error', posix()} when
+ Socket :: socket(),
+ Options :: [socket_getopt()].
getopts(Socket, Opts) ->
prim_inet:getopts(Socket, Opts).
@@ -272,7 +288,19 @@ getopts(Socket, Opts) ->
getifaddrs(Socket) ->
prim_inet:getifaddrs(Socket).
--spec getifaddrs() -> {'ok', [string()]} | {'error', posix()}.
+-spec getifaddrs() -> {ok, Iflist} | {error, posix()} when
+ Iflist :: [{Ifname,[Ifopt]}],
+ Ifname :: string(),
+ Ifopt :: {flag,[Flag]} | {addr,Addr} | {netmask,Netmask}
+ | {broadaddr,Broadaddr} | {dstaddr,Dstaddr}
+ | {hwaddr,Hwaddr},
+ Flag :: up | broadcast | loopback | pointtopoint
+ | running | multicast,
+ Addr :: ip_address(),
+ Netmask :: ip_address(),
+ Broadaddr :: ip_address(),
+ Dstaddr :: ip_address(),
+ Hwaddr :: [byte()].
getifaddrs() ->
withsocket(fun(S) -> prim_inet:getifaddrs(S) end).
@@ -371,7 +399,8 @@ popf(_Socket) ->
% use of the DHCP-protocol
% should never fail
--spec gethostname() -> {'ok', string()}.
+-spec gethostname() -> {'ok', Hostname} when
+ Hostname :: string().
gethostname() ->
case inet_udp:open(0,[]) of
@@ -402,19 +431,23 @@ getstat(Socket) ->
getstat(Socket,What) ->
prim_inet:getstat(Socket, What).
--spec gethostbyname(Name :: string() | atom()) ->
- {'ok', #hostent{}} | {'error', posix()}.
+-spec gethostbyname(Hostname) -> {ok, Hostent} | {error, posix()} when
+ Hostname :: hostname(),
+ Hostent :: hostent().
gethostbyname(Name) ->
gethostbyname_tm(Name, inet, false).
--spec gethostbyname(Name :: string() | atom(), Family :: family_option()) ->
- {'ok', #hostent{}} | {'error', posix()}.
+-spec gethostbyname(Hostname, Family) ->
+ {ok, Hostent} | {error, posix()} when
+ Hostname :: hostname(),
+ Family :: family_option(),
+ Hostent :: hostent().
gethostbyname(Name,Family) ->
gethostbyname_tm(Name, Family, false).
--spec gethostbyname(Name :: string() | atom(),
+-spec gethostbyname(Name :: hostname(),
Family :: family_option(),
Timeout :: non_neg_integer() | 'infinity') ->
{'ok', #hostent{}} | {'error', posix()}.
@@ -439,8 +472,9 @@ gethostbyname_tm(Name,Family,Timer) ->
gethostbyname_tm(Name, Family, Timer, Opts).
--spec gethostbyaddr(Address :: string() | ip_address()) ->
- {'ok', #hostent{}} | {'error', posix()}.
+-spec gethostbyaddr(Address) -> {ok, Hostent} | {error, posix()} when
+ Address :: string() | ip_address(),
+ Hostent :: hostent().
gethostbyaddr(Address) ->
gethostbyaddr_tm(Address, false).
@@ -491,14 +525,15 @@ getfd(Socket) ->
%% Lookup an ip address
%%
--spec getaddr(Host :: ip_address() | string() | atom(),
- Family :: family_option()) ->
- {'ok', ip_address()} | {'error', posix()}.
+-spec getaddr(Host, Family) -> {ok, Address} | {error, posix()} when
+ Host :: ip_address() | hostname(),
+ Family :: family_option(),
+ Address :: ip_address().
getaddr(Address, Family) ->
getaddr(Address, Family, infinity).
--spec getaddr(Host :: ip_address() | string() | atom(),
+-spec getaddr(Host :: ip_address() | hostname(),
Family :: family_option(),
Timeout :: non_neg_integer() | 'infinity') ->
{'ok', ip_address()} | {'error', posix()}.
@@ -515,9 +550,11 @@ getaddr_tm(Address, Family, Timer) ->
Error -> Error
end.
--spec getaddrs(Host :: ip_address() | string() | atom(),
- Family :: family_option()) ->
- {'ok', [ip_address()]} | {'error', posix()}.
+-spec getaddrs(Host, Family) ->
+ {ok, Addresses} | {error, posix()} when
+ Host :: ip_address() | hostname(),
+ Family :: family_option(),
+ Addresses :: [ip_address()].
getaddrs(Address, Family) ->
getaddrs(Address, Family, infinity).
@@ -1237,7 +1274,8 @@ port_list(Name) ->
%% utils
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--spec format_error(posix()) -> string().
+-spec format_error(Posix) -> string() when
+ Posix :: posix().
format_error(exbadport) -> "invalid port state";
format_error(exbadseq) -> "bad command sequence";
diff --git a/lib/kernel/src/inet_res.erl b/lib/kernel/src/inet_res.erl
index de0f23bf24..d1f5644ff7 100644
--- a/lib/kernel/src/inet_res.erl
+++ b/lib/kernel/src/inet_res.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -47,18 +47,93 @@
false -> ok
end).
+-type res_option() ::
+ {alt_nameservers, [nameserver()]}
+ | {edns, 0 | false}
+ | {inet6, boolean()}
+ | {nameservers, [nameserver()]}
+ | {recurse, boolean()}
+ | {retry, integer()}
+ | {timeout, integer()}
+ | {udp_payload_size, integer()}
+ | {usevc, boolean()}.
+
+-type nameserver() :: {inet:ip_address(), Port :: 1..65535}.
+
+-type res_error() :: formerr | qfmterror | servfail | nxdomain |
+ notimp | refused | badvers | timeout.
+
+-type dns_name() :: string().
+
+-type rr_type() :: a | aaaa | cname | gid | hinfo | ns | mb | md | mg | mf
+ | minfo | mx | naptr | null | ptr | soa | spf | srv | txt
+ | uid | uinfo | unspec | wks.
+
+-type dns_class() :: in | chaos | hs | any.
+
+-type dns_msg() :: term().
+
+-type dns_data() ::
+ dns_name()
+ | inet:ip4_address()
+ | inet:ip6_address()
+ | {MName :: dns_name(),
+ RName :: dns_name(),
+ Serial :: integer(),
+ Refresh :: integer(),
+ Retry :: integer(),
+ Expiry :: integer(),
+ Minimum :: integer()}
+ | {inet:ip4_address(), Proto :: integer(), BitMap :: binary()}
+ | {CpuString :: string(), OsString :: string()}
+ | {RM :: dns_name(), EM :: dns_name()}
+ | {Prio :: integer(), dns_name()}
+ | {Prio :: integer(),Weight :: integer(),Port :: integer(),dns_name()}
+ | {Order :: integer(),Preference :: integer(),Flags :: string(),
+ Services :: string(),Regexp :: string(), dns_name()}
+ | [string()]
+ | binary().
+
%% --------------------------------------------------------------------------
%% resolve:
%%
%% Nameserver query
%%
+-spec resolve(Name, Class, Type) -> {ok, dns_msg()} | Error when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Error :: {error, Reason} | {error,{Reason,dns_msg()}},
+ Reason :: inet:posix() | res_error().
+
resolve(Name, Class, Type) ->
resolve(Name, Class, Type, [], infinity).
+-spec resolve(Name, Class, Type, Opts) ->
+ {ok, dns_msg()} | Error when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Opts :: [Opt],
+ Opt :: res_option() | verbose | atom(),
+ Error :: {error, Reason} | {error,{Reason,dns_msg()}},
+ Reason :: inet:posix() | res_error().
+
resolve(Name, Class, Type, Opts) ->
resolve(Name, Class, Type, Opts, infinity).
+-spec resolve(Name, Class, Type, Opts, Timeout) ->
+ {ok, dns_msg()} | Error when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Opts :: [Opt],
+ Opt :: res_option() | verbose | atom(),
+ Timeout :: timeout(),
+ Error :: {error, Reason} | {error,{Reason,dns_msg()}},
+ Reason :: inet:posix() | res_error().
+
resolve(Name, Class, Type, Opts, Timeout) ->
case nsdname(Name) of
{ok, Nm} ->
@@ -76,12 +151,30 @@ resolve(Name, Class, Type, Opts, Timeout) ->
%% Convenience wrapper to resolve/3,4,5 that filters out all answer data
%% fields of the class and type asked for.
+-spec lookup(Name, Class, Type) -> [dns_data()] when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type().
+
lookup(Name, Class, Type) ->
lookup(Name, Class, Type, []).
+-spec lookup(Name, Class, Type, Opts) -> [dns_data()] when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Opts :: [res_option() | verbose].
+
lookup(Name, Class, Type, Opts) ->
lookup(Name, Class, Type, Opts, infinity).
+-spec lookup(Name, Class, Type, Opts, Timeout) -> [dns_data()] when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Opts :: [res_option() | verbose],
+ Timeout :: timeout().
+
lookup(Name, Class, Type, Opts, Timeout) ->
lookup_filter(resolve(Name, Class, Type, Opts, Timeout),
Class, Type).
@@ -101,17 +194,55 @@ lookup_filter({error,_}, _, _) -> [].
%%
%% To be deprecated
+-spec nslookup(Name, Class, Type) -> {ok, dns_msg()} | {error, Reason} when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Reason :: inet:posix() | res_error().
+
nslookup(Name, Class, Type) ->
do_nslookup(Name, Class, Type, [], infinity).
+-spec nslookup(Name, Class, Type, Timeout) ->
+ {ok, dns_msg()} | {error, Reason} when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Timeout :: timeout(),
+ Reason :: inet:posix() | res_error();
+ (Name, Class, Type, Nameservers) ->
+ {ok, dns_msg()} | {error, Reason} when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Nameservers :: [nameserver()],
+ Reason :: inet:posix() | res_error().
+
nslookup(Name, Class, Type, Timeout) when is_integer(Timeout), Timeout >= 0 ->
do_nslookup(Name, Class, Type, [], Timeout);
nslookup(Name, Class, Type, NSs) -> % For backwards compatibility
nnslookup(Name, Class, Type, NSs). % with OTP R6B only
+-spec nnslookup(Name, Class, Type, Nameservers) ->
+ {ok, dns_msg()} | {error, Reason} when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Nameservers :: [nameserver()],
+ Reason :: inet:posix().
+
nnslookup(Name, Class, Type, NSs) ->
nnslookup(Name, Class, Type, NSs, infinity).
+-spec nnslookup(Name, Class, Type, Nameservers, Timeout) ->
+ {ok, dns_msg()} | {error, Reason} when
+ Name :: dns_name() | inet:ip_address(),
+ Class :: dns_class(),
+ Type :: rr_type(),
+ Timeout :: timeout(),
+ Nameservers :: [nameserver()],
+ Reason :: inet:posix().
+
nnslookup(Name, Class, Type, NSs, Timeout) ->
do_nslookup(Name, Class, Type, [{nameservers,NSs}], Timeout).
@@ -192,8 +323,19 @@ make_options(Opts, [Name|Names]) ->
%%
%% --------------------------------------------------------------------------
+-spec gethostbyaddr(Address) -> {ok, Hostent} | {error, Reason} when
+ Address :: inet:ip_address(),
+ Hostent :: inet:hostent(),
+ Reason :: inet:posix() | res_error().
+
gethostbyaddr(IP) -> gethostbyaddr_tm(IP,false).
+-spec gethostbyaddr(Address, Timeout) -> {ok, Hostent} | {error, Reason} when
+ Address :: inet:ip_address(),
+ Timeout :: timeout(),
+ Hostent :: inet:hostent(),
+ Reason :: inet:posix() | res_error().
+
gethostbyaddr(IP,Timeout) ->
Timer = inet:start_timer(Timeout),
Res = gethostbyaddr_tm(IP,Timer),
@@ -249,6 +391,11 @@ res_gethostbyaddr(Addr, IP, Timer) ->
%% Caches the answer.
%% --------------------------------------------------------------------------
+-spec gethostbyname(Name) -> {ok, Hostent} | {error, Reason} when
+ Name :: dns_name(),
+ Hostent :: inet:hostent(),
+ Reason :: inet:posix() | res_error().
+
gethostbyname(Name) ->
case inet_db:res_option(inet6) of
true ->
@@ -257,9 +404,23 @@ gethostbyname(Name) ->
gethostbyname_tm(Name, inet, false)
end.
+-spec gethostbyname(Name, Family) -> {ok, Hostent} | {error, Reason} when
+ Name :: dns_name(),
+ Hostent :: inet:hostent(),
+ Family :: inet:family_option(),
+ Reason :: inet:posix() | res_error().
+
gethostbyname(Name,Family) ->
gethostbyname_tm(Name,Family,false).
+-spec gethostbyname(Name, Family, Timeout) ->
+ {ok, Hostent} | {error, Reason} when
+ Name :: dns_name(),
+ Hostent :: inet:hostent(),
+ Timeout :: timeout(),
+ Family :: inet:family_option(),
+ Reason :: inet:posix() | res_error().
+
gethostbyname(Name,Family,Timeout) ->
Timer = inet:start_timer(Timeout),
Res = gethostbyname_tm(Name,Family,Timer),
@@ -298,14 +459,27 @@ gethostbyname_tm(_Name, _Family, _Timer) ->
%%
%% getbyname(domain_name(), Type) => {ok, hostent()} | {error, Reason}
%%
-%% where domain_name() is domain string or atom and Type is ?S_A, ?S_MX ...
+%% where domain_name() is domain string and Type is ?S_A, ?S_MX ...
%%
%% Caches the answer.
%% --------------------------------------------------------------------------
+-spec getbyname(Name, Type) -> {ok, Hostent} | {error, Reason} when
+ Name :: dns_name(),
+ Type :: rr_type(),
+ Hostent :: inet:hostent(),
+ Reason :: inet:posix() | res_error().
+
getbyname(Name, Type) ->
getbyname_tm(Name,Type,false).
+-spec getbyname(Name, Type, Timeout) -> {ok, Hostent} | {error, Reason} when
+ Name :: dns_name(),
+ Type :: rr_type(),
+ Timeout :: timeout(),
+ Hostent :: inet:hostent(),
+ Reason :: inet:posix() | res_error().
+
getbyname(Name, Type, Timeout) ->
Timer = inet:start_timer(Timeout),
Res = getbyname_tm(Name, Type, Timer),
@@ -539,27 +713,41 @@ udp_send(#sock{inet=I}, {A,B,C,D}=IP, Port, Buffer)
when ?ip(A,B,C,D), ?port(Port) ->
gen_udp:send(I, IP, Port, Buffer).
-udp_recv(#sock{inet6=I}, {A,B,C,D,E,F,G,H}=IP, Port, Timeout)
+udp_recv(#sock{inet6=I}, {A,B,C,D,E,F,G,H}=IP, Port, Timeout, Decode)
when ?ip6(A,B,C,D,E,F,G,H), ?port(Port) ->
- do_udp_recv(fun(T) -> gen_udp:recv(I, 0, T) end, IP, Port, Timeout);
-udp_recv(#sock{inet=I}, {A,B,C,D}=IP, Port, Timeout)
+ do_udp_recv(I, IP, Port, Timeout, Decode, erlang:now(), Timeout);
+udp_recv(#sock{inet=I}, {A,B,C,D}=IP, Port, Timeout, Decode)
when ?ip(A,B,C,D), ?port(Port) ->
- do_udp_recv(fun(T) -> gen_udp:recv(I, 0, T) end, IP, Port, Timeout).
-
-do_udp_recv(Recv, IP, Port, Timeout) ->
- do_udp_recv(Recv, IP, Port, Timeout,
- if Timeout =/= 0 -> erlang:now(); true -> undefined end).
-
-do_udp_recv(Recv, IP, Port, Timeout, Then) ->
- case Recv(Timeout) of
- {ok,{IP,Port,Answer}} ->
- {ok,Answer,erlang:max(0, Timeout - now_ms(erlang:now(), Then))};
- {ok,_} when Timeout =:= 0 ->
- {error,timeout};
- {ok,_} ->
- Now = erlang:now(),
- T = erlang:max(0, Timeout - now_ms(Now, Then)),
- do_udp_recv(Recv, IP, Port, T, Now);
+ do_udp_recv(I, IP, Port, Timeout, Decode, erlang:now(), Timeout).
+
+do_udp_recv(_I, _IP, _Port, 0, _Decode, _Start, _T) ->
+ timeout;
+do_udp_recv(I, IP, Port, Timeout, Decode, Start, T) ->
+ case gen_udp:recv(I, 0, T) of
+ {ok,Reply} ->
+ case Decode(Reply) of
+ false when T =:= 0 ->
+ %% This is a compromize between the hard way i.e
+ %% in the clause below if NewT becomes 0 bailout
+ %% immediately and risk that the right reply lies
+ %% ahead after some bad id replies, and the
+ %% forgiving way i.e go on with Timeout 0 until
+ %% the right reply comes or no reply (timeout)
+ %% which opens for a DOS attack by a malicious
+ %% DNS server flooding with bad id replies causing
+ %% an infinite loop here.
+ %%
+ %% Timeout is used as a sanity limit counter
+ %% just to put an end to the loop.
+ NewTimeout = erlang:max(0, Timeout - 50),
+ do_udp_recv(I, IP, Port, NewTimeout, Decode, Start, T);
+ false ->
+ Now = erlang:now(),
+ NewT = erlang:max(0, Timeout - now_ms(Now, Start)),
+ do_udp_recv(I, IP, Port, Timeout, Decode, Start, NewT);
+ Result ->
+ Result
+ end;
Error -> Error
end.
@@ -580,6 +768,17 @@ udp_close(#sock{inet=I,inet6=I6}) ->
%% end
%% end
%%
+%% But that man page also says dig always use num_servers = 1.
+%%
+%% Our man page says: timeout/retry, then double for next retry, i.e
+%% for i = 0 to retry - 1
+%% foreach nameserver
+%% send query
+%% wait((time * (2**i)) / retry)
+%% end
+%% end
+%%
+%% And that is what the code seems to do, now fixed, hopefully...
do_query(_Q, [], _Timer) ->
{error,nxdomain};
@@ -589,19 +788,16 @@ do_query(#q{options=#options{retry=Retry}}=Q, NSs, Timer) ->
query_retries(_Q, _NSs, _Timer, Retry, Retry, S) ->
udp_close(S),
{error,timeout};
+query_retries(_Q, [], _Timer, _Retry, _I, S) ->
+ udp_close(S),
+ {error,timeout};
query_retries(Q, NSs, Timer, Retry, I, S0) ->
- Num = length(NSs),
- if Num =:= 0 ->
- udp_close(S0),
- {error,timeout};
- true ->
- case query_nss(Q, NSs, Timer, Retry, I, S0, []) of
- {S,{noanswer,ErrNSs}} -> %% remove unreachable nameservers
- query_retries(Q, NSs--ErrNSs, Timer, Retry, I+1, S);
- {S,Result} ->
- udp_close(S),
- Result
- end
+ case query_nss(Q, NSs, Timer, Retry, I, S0, []) of
+ {S,{noanswer,ErrNSs}} -> %% remove unreachable nameservers
+ query_retries(Q, NSs--ErrNSs, Timer, Retry, I+1, S);
+ {S,Result} ->
+ udp_close(S),
+ Result
end.
query_nss(_Q, [], _Timer, _Retry, _I, S, ErrNSs) ->
@@ -611,13 +807,13 @@ query_nss(#q{edns=undefined}=Q, NSs, Timer, Retry, I, S, ErrNSs) ->
query_nss(Q, NSs, Timer, Retry, I, S, ErrNSs) ->
query_nss_edns(Q, NSs, Timer, Retry, I, S, ErrNSs).
-query_nss_edns(#q{options=#options{udp_payload_size=PSz}=Options,
- edns={Id,Buffer}}=Q,
- [{IP,Port}=NS|NSs]=NSs0, Timer, Retry, I, S0, ErrNSs) ->
- {S,Res}=Reply = query_ns(S0, Id, Buffer, IP, Port, Timer,
- Retry, I, Options, PSz),
+query_nss_edns(
+ #q{options=#options{udp_payload_size=PSz}=Options,edns={Id,Buffer}}=Q,
+ [{IP,Port}=NS|NSs]=NSs0, Timer, Retry, I, S0, ErrNSs) ->
+ {S,Res}=Reply =
+ query_ns(S0, Id, Buffer, IP, Port, Timer, Retry, I, Options, PSz),
case Res of
- timeout -> {S,{error,timeout}};
+ timeout -> {S,{error,timeout}}; % Bailout timeout
{ok,_} -> Reply;
{error,{nxdomain,_}} -> Reply;
{error,{E,_}} when E =:= qfmterror; E =:= notimp; E =:= servfail;
@@ -629,17 +825,19 @@ query_nss_edns(#q{options=#options{udp_payload_size=PSz}=Options,
query_nss(Q, NSs, Timer, Retry, I, S, ErrNSs)
end.
-query_nss_dns(#q{dns=Qdns}=Q0, [{IP,Port}=NS|NSs],
- Timer, Retry, I, S0, ErrNSs) ->
+query_nss_dns(
+ #q{dns=Qdns}=Q0,
+ [{IP,Port}=NS|NSs], Timer, Retry, I, S0, ErrNSs) ->
#q{options=Options,dns={Id,Buffer}}=Q =
if
is_function(Qdns, 0) -> Q0#q{dns=Qdns()};
true -> Q0
end,
- {S,Res}=Reply = query_ns(S0, Id, Buffer, IP, Port, Timer,
- Retry, I, Options, ?PACKETSZ),
+ {S,Res}=Reply =
+ query_ns(
+ S0, Id, Buffer, IP, Port, Timer, Retry, I, Options, ?PACKETSZ),
case Res of
- timeout -> {S,{error,timeout}};
+ timeout -> {S,{error,timeout}}; % Bailout timeout
{ok,_} -> Reply;
{error,{E,_}} when E =:= nxdomain; E =:= qfmterror -> Reply;
{error,E} when E =:= fmt; E =:= enetunreach; E =:= econnrefused ->
@@ -653,48 +851,66 @@ query_ns(S0, Id, Buffer, IP, Port, Timer, Retry, I,
PSz) ->
case UseVC orelse iolist_size(Buffer) > PSz of
true ->
- {S0,query_tcp(Tm, Id, Buffer, IP, Port, Timer, Verbose)};
+ TcpTimeout = inet:timeout(Tm*5, Timer),
+ {S0,query_tcp(TcpTimeout, Id, Buffer, IP, Port, Verbose)};
false ->
case udp_open(S0, IP) of
{ok,S} ->
- {S,case query_udp(S, Id, Buffer, IP, Port, Timer,
- Retry, I, Tm, Verbose) of
- {ok,#dns_rec{header=H}} when H#dns_header.tc ->
- query_tcp(Tm, Id, Buffer,
- IP, Port, Timer, Verbose);
- Reply -> Reply
- end};
+ Timeout =
+ inet:timeout( (Tm * (1 bsl I)) div Retry, Timer),
+ {S,
+ case query_udp(
+ S, Id, Buffer, IP, Port, Timeout, Verbose) of
+ {ok,#dns_rec{header=H}} when H#dns_header.tc ->
+ TcpTimeout = inet:timeout(Tm*5, Timer),
+ query_tcp(
+ TcpTimeout, Id, Buffer, IP, Port, Verbose);
+ Reply -> Reply
+ end};
Error ->
{S0,Error}
end
end.
-query_udp(S, Id, Buffer, IP, Port, Timer, Retry, I, Tm, Verbose) ->
- Timeout = inet:timeout( (Tm * (1 bsl I)) div Retry, Timer),
+query_udp(_S, _Id, _Buffer, _IP, _Port, 0, _Verbose) ->
+ timeout;
+query_udp(S, Id, Buffer, IP, Port, Timeout, Verbose) ->
?verbose(Verbose, "Try UDP server : ~p:~p (timeout=~w)\n",
- [IP, Port, Timeout]),
- udp_connect(S, IP, Port),
- udp_send(S, IP, Port, Buffer),
- query_udp_recv(S, IP, Port, Id, Timeout, Verbose).
-
-query_udp_recv(S, IP, Port, Id, Timeout, Verbose) ->
- case udp_recv(S, IP, Port, Timeout) of
- {ok,Answer,T} ->
- case decode_answer(Answer, Id, Verbose) of
- {error, badid} ->
- query_udp_recv(S, IP, Port, Id, T, Verbose);
- Reply -> Reply
+ [IP,Port,Timeout]),
+ case
+ case udp_connect(S, IP, Port) of
+ ok ->
+ udp_send(S, IP, Port, Buffer);
+ E1 ->
+ E1 end of
+ ok ->
+ Decode =
+ fun ({RecIP,RecPort,Answer})
+ when RecIP =:= IP, RecPort =:= Port ->
+ case decode_answer(Answer, Id, Verbose) of
+ {error,badid} ->
+ false;
+ Reply ->
+ Reply
+ end;
+ ({_,_,_}) ->
+ false
+ end,
+ case udp_recv(S, IP, Port, Timeout, Decode) of
+ {ok,_}=Result ->
+ Result;
+ E2 ->
+ ?verbose(Verbose, "UDP server error: ~p\n", [E2]),
+ E2
end;
- {error, timeout} when Timeout =:= 0 ->
- ?verbose(Verbose, "UDP server timeout\n", []),
- timeout;
- Error ->
- ?verbose(Verbose, "UDP server error: ~p\n", [Error]),
- Error
+ E3 ->
+ ?verbose(Verbose, "UDP send failed: ~p\n", [E3]),
+ {error,econnrefused}
end.
-query_tcp(Tm, Id, Buffer, IP, Port, Timer, Verbose) ->
- Timeout = inet:timeout(Tm*5, Timer),
+query_tcp(0, _Id, _Buffer, _IP, _Port, _Verbose) ->
+ timeout;
+query_tcp(Timeout, Id, Buffer, IP, Port, Verbose) ->
?verbose(Verbose, "Try TCP server : ~p:~p (timeout=~w)\n",
[IP, Port, Timeout]),
Family = case IP of
@@ -716,19 +932,10 @@ query_tcp(Tm, Id, Buffer, IP, Port, Timer, Verbose) ->
end;
Error ->
gen_tcp:close(S),
- case Error of
- {error, timeout} when Timeout =:= 0 ->
- ?verbose(Verbose, "TCP server recv timeout\n", []),
- timeout;
- _ ->
- ?verbose(Verbose, "TCP server recv error: ~p\n",
- [Error]),
- Error
- end
+ ?verbose(Verbose, "TCP server recv error: ~p\n",
+ [Error]),
+ Error
end;
- {error, timeout} when Timeout =:= 0 ->
- ?verbose(Verbose, "TCP server connect timeout\n", []),
- timeout;
Error ->
?verbose(Verbose, "TCP server error: ~p\n", [Error]),
Error
diff --git a/lib/kernel/src/inet_udp.erl b/lib/kernel/src/inet_udp.erl
index 9a4089ab19..60bd96f332 100644
--- a/lib/kernel/src/inet_udp.erl
+++ b/lib/kernel/src/inet_udp.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -39,8 +39,10 @@ getserv(Name) when is_atom(Name) -> inet:getservbyname(Name,udp).
getaddr(Address) -> inet:getaddr(Address, inet).
getaddr(Address,Timer) -> inet:getaddr_tm(Address, inet, Timer).
+-spec open(_) -> {ok, inet:socket()} | {error, atom()}.
open(Port) -> open(Port, []).
+-spec open(_, _) -> {ok, inet:socket()} | {error, atom()}.
open(Port, Opts) ->
case inet:udp_options(
[{port,Port}, {recbuf, ?RECBUF} | Opts],
@@ -69,6 +71,8 @@ recv(S,Len) ->
recv(S,Len,Time) ->
prim_inet:recvfrom(S, Len, Time).
+-spec close(inet:socket()) -> ok.
+
close(S) ->
inet:udp_close(S).
diff --git a/lib/kernel/src/net_adm.erl b/lib/kernel/src/net_adm.erl
index 737b1ecee9..9b2dac9544 100644
--- a/lib/kernel/src/net_adm.erl
+++ b/lib/kernel/src/net_adm.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -35,7 +35,11 @@
%% Try to read .hosts.erlang file in
%% 1. cwd , 2. $HOME 3. init:root_dir()
--spec host_file() -> [atom()] | {'error',atom() | {integer(),atom(),_}}.
+-spec host_file() -> Hosts | {error, Reason} when
+ Hosts :: [Host :: atom()],
+ %% Copied from file:path_consult/2:
+ Reason :: file:posix() | badarg | terminated | system_limit
+ | {Line :: integer(), Mod :: module(), Term :: term()}.
host_file() ->
Home = case init:get_argument(home) of
@@ -50,7 +54,8 @@ host_file() ->
%% Check whether a node is up or down
%% side effect: set up a connection to Node if there not yet is one.
--spec ping(atom()) -> 'pang' | 'pong'.
+-spec ping(Node) -> pong | pang when
+ Node :: atom().
ping(Node) when is_atom(Node) ->
case catch gen:call({net_kernel, Node},
@@ -63,7 +68,8 @@ ping(Node) when is_atom(Node) ->
pang
end.
--spec localhost() -> string().
+-spec localhost() -> Name when
+ Name :: string().
localhost() ->
{ok, Host} = inet:gethostname(),
@@ -73,12 +79,20 @@ localhost() ->
end.
--spec names() -> {'ok', [{string(), integer()}]} | {'error', _}.
+-spec names() -> {ok, [{Name, Port}]} | {error, Reason} when
+ Name :: string(),
+ Port :: non_neg_integer(),
+ Reason :: address | file:posix().
names() ->
names(localhost()).
--spec names(atom() | string()) -> {'ok', [{string(), integer()}]} | {'error', _}.
+
+-spec names(Host) -> {ok, [{Name, Port}]} | {error, Reason} when
+ Host :: atom() | string(),
+ Name :: string(),
+ Port :: non_neg_integer(),
+ Reason :: address | file:posix().
names(Hostname) ->
case inet:gethostbyname(Hostname) of
@@ -88,8 +102,9 @@ names(Hostname) ->
Else
end.
--spec dns_hostname(atom() | string()) ->
- {'ok', string()} | {'error', atom() | string()}.
+-spec dns_hostname(Host) -> {ok, Name} | {error, Host} when
+ Host :: atom() | string(),
+ Name :: string().
dns_hostname(Hostname) ->
case inet:gethostbyname(Hostname) of
@@ -164,7 +179,8 @@ collect_new(Sofar, Nodelist) ->
world() ->
world(silent).
--spec world(verbosity()) -> [node()].
+-spec world(Arg) -> [node()] when
+ Arg :: verbosity().
world(Verbose) ->
case net_adm:host_file() of
@@ -172,12 +188,15 @@ world(Verbose) ->
Hosts -> expand_hosts(Hosts, Verbose)
end.
--spec world_list([atom()]) -> [node()].
+-spec world_list(Hosts) -> [node()] when
+ Hosts :: [atom()].
world_list(Hosts) when is_list(Hosts) ->
expand_hosts(Hosts, silent).
--spec world_list([atom()], verbosity()) -> [node()].
+-spec world_list(Hosts, Arg) -> [node()] when
+ Hosts :: [atom()],
+ Arg :: verbosity().
world_list(Hosts, Verbose) when is_list(Hosts) ->
expand_hosts(Hosts, Verbose).
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index 49a02359b0..9e3d730cee 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -145,8 +145,15 @@
%% Interface functions
kernel_apply(M,F,A) -> request({apply,M,F,A}).
+
+-spec allow(Nodes) -> ok | error when
+ Nodes :: [node()].
allow(Nodes) -> request({allow, Nodes}).
+
longnames() -> request(longnames).
+
+-spec stop() -> ok | {error, Reason} when
+ Reason :: not_allowed | not_found.
stop() -> erl_distribution:stop().
node_info(Node) -> get_node_info(Node).
@@ -158,10 +165,28 @@ i(Node) -> print_info(Node).
verbose(Level) when is_integer(Level) ->
request({verbose, Level}).
+-spec set_net_ticktime(NetTicktime, TransitionPeriod) -> Res when
+ NetTicktime :: pos_integer(),
+ TransitionPeriod :: non_neg_integer(),
+ Res :: unchanged
+ | change_initiated
+ | {ongoing_change_to, NewNetTicktime},
+ NewNetTicktime :: pos_integer().
set_net_ticktime(T, TP) when is_integer(T), T > 0, is_integer(TP), TP >= 0 ->
ticktime_res(request({new_ticktime, T*250, TP*1000})).
+
+-spec set_net_ticktime(NetTicktime) -> Res when
+ NetTicktime :: pos_integer(),
+ Res :: unchanged
+ | change_initiated
+ | {ongoing_change_to, NewNetTicktime},
+ NewNetTicktime :: pos_integer().
set_net_ticktime(T) when is_integer(T) ->
set_net_ticktime(T, ?DEFAULT_TRANSITION_PERIOD).
+
+-spec get_net_ticktime() -> Res when
+ Res :: NetTicktime | {ongoing_change_to, NetTicktime} | ignored,
+ NetTicktime :: pos_integer().
get_net_ticktime() ->
ticktime_res(request(ticktime)).
@@ -171,6 +196,9 @@ get_net_ticktime() ->
%% flags (we may want to move it elsewhere later). In order to easily
%% be backward compatible, errors are created here when process_flag()
%% fails.
+-spec monitor_nodes(Flag) -> ok | Error when
+ Flag :: boolean(),
+ Error :: error | {error, term()}.
monitor_nodes(Flag) ->
case catch process_flag(monitor_nodes, Flag) of
true -> ok;
@@ -178,6 +206,13 @@ monitor_nodes(Flag) ->
_ -> mk_monitor_nodes_error(Flag, [])
end.
+-spec monitor_nodes(Flag, Options) -> ok | Error when
+ Flag :: boolean(),
+ Options :: [Option],
+ Option :: {node_type, NodeType}
+ | nodedown_reason,
+ NodeType :: visible | hidden | all,
+ Error :: error | {error, term()}.
monitor_nodes(Flag, Opts) ->
case catch process_flag({monitor_nodes, Opts}, Flag) of
true -> ok;
@@ -209,6 +244,8 @@ publish_on_node(Node) when is_atom(Node) ->
update_publish_nodes(Ns) ->
request({update_publish_nodes, Ns}).
+-spec connect_node(Node) -> boolean() | ignored when
+ Node :: node().
%% explicit connects
connect_node(Node) when is_atom(Node) ->
request({connect, normal, Node}).
@@ -1249,7 +1286,7 @@ protocol_childspecs([H|T]) ->
epmd_module() ->
case init:get_argument(epmd_module) of
{ok,[[Module]]} ->
- Module;
+ list_to_atom(Module);
_ ->
erl_epmd
end.
diff --git a/lib/kernel/src/os.erl b/lib/kernel/src/os.erl
index d1feae771d..f6769df585 100644
--- a/lib/kernel/src/os.erl
+++ b/lib/kernel/src/os.erl
@@ -24,7 +24,10 @@
-include("file.hrl").
--spec type() -> 'vxworks' | {'unix',atom()} | {'win32',atom()} | {'ose',atom()}.
+-spec type() -> vxworks | {Osfamily, Osname} when
+ Osfamily :: unix | win32,
+ Osname :: atom().
+
type() ->
case erlang:system_info(os_type) of
{vxworks, _} ->
@@ -32,18 +35,27 @@ type() ->
Else -> Else
end.
--spec version() -> string() | {non_neg_integer(),non_neg_integer(),non_neg_integer()}.
+-spec version() -> VersionString | {Major, Minor, Release} when
+ VersionString :: string(),
+ Major :: non_neg_integer(),
+ Minor :: non_neg_integer(),
+ Release :: non_neg_integer().
version() ->
erlang:system_info(os_version).
--spec find_executable(string()) -> string() | 'false'.
+-spec find_executable(Name) -> Filename | 'false' when
+ Name :: string(),
+ Filename :: string().
find_executable(Name) ->
case os:getenv("PATH") of
false -> find_executable(Name, []);
Path -> find_executable(Name, Path)
end.
--spec find_executable(string(), string()) -> string() | 'false'.
+-spec find_executable(Name, Path) -> Filename | 'false' when
+ Name :: string(),
+ Path :: string(),
+ Filename :: string().
find_executable(Name, Path) ->
Extensions = extensions(),
case filename:pathtype(Name) of
@@ -147,7 +159,8 @@ extensions() ->
end.
%% Executes the given command in the default shell for the operating system.
--spec cmd(atom() | string() | [string()]) -> string().
+-spec cmd(Command) -> string() when
+ Command :: atom() | io_lib:chars().
cmd(Cmd) ->
validate(Cmd),
case type() of
diff --git a/lib/kernel/src/pg2.erl b/lib/kernel/src/pg2.erl
index 956a900adc..0d5838716e 100644
--- a/lib/kernel/src/pg2.erl
+++ b/lib/kernel/src/pg2.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1997-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -30,17 +30,19 @@
%%% Exported functions
%%%
--spec start_link() -> {'ok', pid()} | {'error', term()}.
+-spec start_link() -> {'ok', pid()} | {'error', any()}.
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
--spec start() -> {'ok', pid()} | {'error', term()}.
+-spec start() -> {'ok', pid()} | {'error', any()}.
start() ->
ensure_started().
--spec create(term()) -> 'ok'.
+-type name() :: any().
+
+-spec create(Name :: name()) -> 'ok'.
create(Name) ->
ensure_started(),
@@ -55,9 +57,7 @@ create(Name) ->
ok
end.
--type name() :: term().
-
--spec delete(name()) -> 'ok'.
+-spec delete(Name :: name()) -> 'ok'.
delete(Name) ->
ensure_started(),
@@ -67,7 +67,8 @@ delete(Name) ->
end),
ok.
--spec join(name(), pid()) -> 'ok' | {'error', {'no_such_group', term()}}.
+-spec join(Name, Pid :: pid()) -> 'ok' | {'error', {'no_such_group', Name}}
+ when Name :: name().
join(Name, Pid) when is_pid(Pid) ->
ensure_started(),
@@ -83,7 +84,8 @@ join(Name, Pid) when is_pid(Pid) ->
ok
end.
--spec leave(name(), pid()) -> 'ok' | {'error', {'no_such_group', name()}}.
+-spec leave(Name, Pid :: pid()) -> 'ok' | {'error', {'no_such_group', Name}}
+ when Name :: name().
leave(Name, Pid) when is_pid(Pid) ->
ensure_started(),
@@ -99,10 +101,9 @@ leave(Name, Pid) when is_pid(Pid) ->
ok
end.
--type get_members_ret() :: [pid()] | {'error', {'no_such_group', name()}}.
+-spec get_members(Name) -> [pid()] | {'error', {'no_such_group', Name}}
+ when Name :: name().
--spec get_members(name()) -> get_members_ret().
-
get_members(Name) ->
ensure_started(),
case ets:member(pg2_table, {group, Name}) of
@@ -112,7 +113,8 @@ get_members(Name) ->
{error, {no_such_group, Name}}
end.
--spec get_local_members(name()) -> get_members_ret().
+-spec get_local_members(Name) -> [pid()] | {'error', {'no_such_group', Name}}
+ when Name :: name().
get_local_members(Name) ->
ensure_started(),
@@ -123,15 +125,15 @@ get_local_members(Name) ->
{error, {no_such_group, Name}}
end.
--spec which_groups() -> [name()].
+-spec which_groups() -> [Name :: name()].
which_groups() ->
ensure_started(),
all_groups().
--type gcp_error_reason() :: {'no_process', term()} | {'no_such_group', term()}.
-
--spec get_closest_pid(term()) -> pid() | {'error', gcp_error_reason()}.
+-spec get_closest_pid(Name) -> pid() | {'error', Reason} when
+ Name :: name(),
+ Reason :: {'no_process', Name} | {'no_such_group', Name}.
get_closest_pid(Name) ->
case get_local_members(Name) of
@@ -157,7 +159,9 @@ get_closest_pid(Name) ->
-record(state, {}).
--spec init([]) -> {'ok', #state{}}.
+-opaque state() :: #state{}.
+
+-spec init(Arg :: []) -> {'ok', state()}.
init([]) ->
Ns = nodes(),
@@ -169,13 +173,13 @@ init([]) ->
pg2_table = ets:new(pg2_table, [ordered_set, protected, named_table]),
{ok, #state{}}.
--type call() :: {'create', name()}
- | {'delete', name()}
- | {'join', name(), pid()}
- | {'leave', name(), pid()}.
-
--spec handle_call(call(), _, #state{}) ->
- {'reply', 'ok', #state{}}.
+-spec handle_call(Call :: {'create', Name}
+ | {'delete', Name}
+ | {'join', Name, Pid :: pid()}
+ | {'leave', Name, Pid :: pid()},
+ From :: {pid(),Tag :: any()},
+ State :: state()) -> {'reply', 'ok', state()}
+ when Name :: name().
handle_call({create, Name}, _From, S) ->
assure_group(Name),
@@ -195,11 +199,10 @@ handle_call(Request, From, S) ->
[Request, From]),
{noreply, S}.
--type all_members() :: [[name(),...]].
--type cast() :: {'exchange', node(), all_members()}
- | {'del_member', name(), pid()}.
-
--spec handle_cast(cast(), #state{}) -> {'noreply', #state{}}.
+-spec handle_cast(Cast :: {'exchange', node(), Names :: [[Name,...]]}
+ | {'del_member', Name, Pid :: pid()},
+ State :: state()) -> {'noreply', state()}
+ when Name :: name().
handle_cast({exchange, _Node, List}, S) ->
store(List),
@@ -208,7 +211,8 @@ handle_cast(_, S) ->
%% Ignore {del_member, Name, Pid}.
{noreply, S}.
--spec handle_info(tuple(), #state{}) -> {'noreply', #state{}}.
+-spec handle_info(Tuple :: tuple(), State :: state()) ->
+ {'noreply', state()}.
handle_info({'DOWN', MonitorRef, process, _Pid, _Info}, S) ->
member_died(MonitorRef),
@@ -222,7 +226,7 @@ handle_info({new_pg2, Node}, S) ->
handle_info(_, S) ->
{noreply, S}.
--spec terminate(term(), #state{}) -> 'ok'.
+-spec terminate(Reason :: any(), State :: state()) -> 'ok'.
terminate(_Reason, _S) ->
true = ets:delete(pg2_table),
diff --git a/lib/kernel/src/rpc.erl b/lib/kernel/src/rpc.erl
index e09acb5024..be35f99ed2 100644
--- a/lib/kernel/src/rpc.erl
+++ b/lib/kernel/src/rpc.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -263,14 +263,28 @@ proxy_user_flush() ->
%% THE rpc client interface
--spec call(node(), atom(), atom(), [term()]) -> term().
+-spec call(Node, Module, Function, Args) -> Res | {badrpc, Reason} when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Res :: term(),
+ Reason :: term().
call(N,M,F,A) when node() =:= N -> %% Optimize local call
local_call(M, F, A);
call(N,M,F,A) ->
do_call(N, {call,M,F,A,group_leader()}, infinity).
--spec call(node(), atom(), atom(), [term()], timeout()) -> term().
+-spec call(Node, Module, Function, Args, Timeout) ->
+ Res | {badrpc, Reason} when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Res :: term(),
+ Reason :: term(),
+ Timeout :: timeout().
call(N,M,F,A,_Timeout) when node() =:= N -> %% Optimize local call
local_call(M,F,A);
@@ -279,14 +293,28 @@ call(N,M,F,A,infinity) ->
call(N,M,F,A,Timeout) when is_integer(Timeout), Timeout >= 0 ->
do_call(N, {call,M,F,A,group_leader()}, Timeout).
--spec block_call(node(), atom(), atom(), [term()]) -> term().
+-spec block_call(Node, Module, Function, Args) -> Res | {badrpc, Reason} when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Res :: term(),
+ Reason :: term().
block_call(N,M,F,A) when node() =:= N -> %% Optimize local call
local_call(M,F,A);
block_call(N,M,F,A) ->
do_call(N, {block_call,M,F,A,group_leader()}, infinity).
--spec block_call(node(), atom(), atom(), [term()], timeout()) -> term().
+-spec block_call(Node, Module, Function, Args, Timeout) ->
+ Res | {badrpc, Reason} when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Res :: term(),
+ Reason :: term(),
+ Timeout :: timeout().
block_call(N,M,F,A,_Timeout) when node() =:= N -> %% Optimize local call
local_call(M, F, A);
@@ -339,7 +367,13 @@ rpc_check(X) -> X.
%% The entire call is packed into an atomic transaction which
%% either succeeds or fails, i.e. never hangs (unless the server itself hangs).
--spec server_call(node(), atom(), term(), term()) -> term() | {'error', 'nodedown'}.
+-spec server_call(Node, Name, ReplyWrapper, Msg) -> Reply | {error, Reason} when
+ Node :: node(),
+ Name :: atom(),
+ ReplyWrapper :: term(),
+ Msg :: term(),
+ Reply :: term(),
+ Reason :: nodedown.
server_call(Node, Name, ReplyWrapper, Msg)
when is_atom(Node), is_atom(Name) ->
@@ -362,7 +396,11 @@ server_call(Node, Name, ReplyWrapper, Msg)
end
end.
--spec cast(node(), atom(), atom(), [term()]) -> 'true'.
+-spec cast(Node, Module, Function, Args) -> true when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
cast(Node, Mod, Fun, Args) when Node =:= node() ->
catch spawn(Mod, Fun, Args),
@@ -373,12 +411,17 @@ cast(Node, Mod, Fun, Args) ->
%% Asynchronous broadcast, returns nothing, it's just send'n prey
--spec abcast(atom(), term()) -> 'abcast'.
+-spec abcast(Name, Msg) -> abcast when
+ Name :: atom(),
+ Msg :: term().
abcast(Name, Mess) ->
abcast([node() | nodes()], Name, Mess).
--spec abcast([node()], atom(), term()) -> 'abcast'.
+-spec abcast(Nodes, Name, Msg) -> abcast when
+ Nodes :: [node()],
+ Name :: atom(),
+ Msg :: term().
abcast([Node|Tail], Name, Mess) ->
Dest = {Name,Node},
@@ -396,23 +439,39 @@ abcast([], _,_) -> abcast.
%% message when we return from the call, we can't know that they have
%% processed the message though.
--spec sbcast(atom(), term()) -> {[node()], [node()]}.
+-spec sbcast(Name, Msg) -> {GoodNodes, BadNodes} when
+ Name :: atom(),
+ Msg :: term(),
+ GoodNodes :: [node()],
+ BadNodes :: [node()].
sbcast(Name, Mess) ->
sbcast([node() | nodes()], Name, Mess).
--spec sbcast([node()], atom(), term()) -> {[node()], [node()]}.
+-spec sbcast(Nodes, Name, Msg) -> {GoodNodes, BadNodes} when
+ Name :: atom(),
+ Msg :: term(),
+ Nodes :: [node()],
+ GoodNodes :: [node()],
+ BadNodes :: [node()].
sbcast(Nodes, Name, Mess) ->
Monitors = send_nodes(Nodes, ?NAME, {sbcast, Name, Mess}, []),
rec_nodes(?NAME, Monitors).
--spec eval_everywhere(atom(), atom(), [term()]) -> 'abcast'.
+-spec eval_everywhere(Module, Function, Args) -> abcast when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
eval_everywhere(Mod, Fun, Args) ->
eval_everywhere([node() | nodes()] , Mod, Fun, Args).
--spec eval_everywhere([node()], atom(), atom(), [term()]) -> 'abcast'.
+-spec eval_everywhere(Nodes, Module, Function, Args) -> abcast when
+ Nodes :: [node()],
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()].
eval_everywhere(Nodes, Mod, Fun, Args) ->
gen_server:abcast(Nodes, ?NAME, {cast,Mod,Fun,Args,group_leader()}).
@@ -453,20 +512,45 @@ unmonitor(Ref) when is_reference(Ref) ->
%% Call apply(M,F,A) on all nodes in parallel
--spec multicall(atom(), atom(), [term()]) -> {[_], [node()]}.
+-spec multicall(Module, Function, Args) -> {ResL, BadNodes} when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ ResL :: [term()],
+ BadNodes :: [node()].
multicall(M, F, A) ->
multicall(M, F, A, infinity).
--spec multicall([node()], atom(), atom(), [term()]) -> {[_], [node()]}
- ; (atom(), atom(), [term()], timeout()) -> {[_], [node()]}.
+-spec multicall(Nodes, Module, Function, Args) -> {ResL, BadNodes} when
+ Nodes :: [node()],
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ ResL :: [term()],
+ BadNodes :: [node()];
+ (Module, Function, Args, Timeout) -> {ResL, BadNodes} when
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Timeout :: timeout(),
+ ResL :: [term()],
+ BadNodes :: [node()].
multicall(Nodes, M, F, A) when is_list(Nodes) ->
multicall(Nodes, M, F, A, infinity);
multicall(M, F, A, Timeout) ->
multicall([node() | nodes()], M, F, A, Timeout).
--spec multicall([node()], atom(), atom(), [term()], timeout()) -> {[_], [node()]}.
+-spec multicall(Nodes, Module, Function, Args, Timeout) ->
+ {ResL, BadNodes} when
+ Nodes :: [node()],
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Timeout :: timeout(),
+ ResL :: [term()],
+ BadNodes :: [node()].
multicall(Nodes, M, F, A, infinity)
when is_list(Nodes), is_atom(M), is_atom(F), is_list(A) ->
@@ -495,12 +579,21 @@ do_multicall(Nodes, M, F, A, Timeout) ->
%%
%% There is no apparent order among the replies.
--spec multi_server_call(atom(), term()) -> {[_], [node()]}.
+-spec multi_server_call(Name, Msg) -> {Replies, BadNodes} when
+ Name :: atom(),
+ Msg :: term(),
+ Replies :: [Reply :: term()],
+ BadNodes :: [node()].
multi_server_call(Name, Msg) ->
multi_server_call([node() | nodes()], Name, Msg).
--spec multi_server_call([node()], atom(), term()) -> {[_], [node()]}.
+-spec multi_server_call(Nodes, Name, Msg) -> {Replies, BadNodes} when
+ Nodes :: [node()],
+ Name :: atom(),
+ Msg :: term(),
+ Replies :: [Reply :: term()],
+ BadNodes :: [node()].
multi_server_call(Nodes, Name, Msg)
when is_list(Nodes), is_atom(Name) ->
@@ -509,9 +602,22 @@ multi_server_call(Nodes, Name, Msg)
%% Deprecated functions. Were only needed when communicating with R6 nodes.
+-spec safe_multi_server_call(Name, Msg) -> {Replies, BadNodes} when
+ Name :: atom(),
+ Msg :: term(),
+ Replies :: [Reply :: term()],
+ BadNodes :: [node()].
+
safe_multi_server_call(Name, Msg) ->
multi_server_call(Name, Msg).
+-spec safe_multi_server_call(Nodes, Name, Msg) -> {Replies, BadNodes} when
+ Nodes :: [node()],
+ Name :: atom(),
+ Msg :: term(),
+ Replies :: [Reply :: term()],
+ BadNodes :: [node()].
+
safe_multi_server_call(Nodes, Name, Msg) ->
multi_server_call(Nodes, Name, Msg).
@@ -539,7 +645,14 @@ rec_nodes(Name, [{N,R} | Tail], Badnodes, Replies) ->
%% rpc's towards the same node. I.e. it returns immediately and
%% it returns a Key that can be used in a subsequent yield(Key).
--spec async_call(node(), atom(), atom(), [term()]) -> pid().
+-opaque key() :: pid().
+
+-spec async_call(Node, Module, Function, Args) -> Key when
+ Node :: node(),
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ Key :: key().
async_call(Node, Mod, Fun, Args) ->
ReplyTo = self(),
@@ -549,20 +662,27 @@ async_call(Node, Mod, Fun, Args) ->
ReplyTo ! {self(), {promise_reply, R}} %% self() is key
end).
--spec yield(pid()) -> term().
+-spec yield(Key) -> {value, Val} | timeout when
+ Key :: key(),
+ Val :: (Res :: term()) | {badrpc, Reason :: term()}.
yield(Key) when is_pid(Key) ->
{value,R} = do_yield(Key, infinity),
R.
--spec nb_yield(pid(), timeout()) -> {'value', _} | 'timeout'.
+-spec nb_yield(Key, Timeout) -> {value, Val} | timeout when
+ Key :: key(),
+ Timeout :: timeout(),
+ Val :: (Res :: term()) | {badrpc, Reason :: term()}.
nb_yield(Key, infinity=Inf) when is_pid(Key) ->
do_yield(Key, Inf);
nb_yield(Key, Timeout) when is_pid(Key), is_integer(Timeout), Timeout >= 0 ->
do_yield(Key, Timeout).
--spec nb_yield(pid()) -> {'value', _} | 'timeout'.
+-spec nb_yield(Key) -> {value, Val} | timeout when
+ Key :: key(),
+ Val :: (Res :: term()) | {badrpc, Reason :: term()}.
nb_yield(Key) when is_pid(Key) ->
do_yield(Key, 0).
@@ -582,7 +702,12 @@ do_yield(Key, Timeout) ->
%% ArgL === [{M,F,Args},........]
%% Returns a lists of the evaluations in the same order as
%% given to ArgL
--spec parallel_eval([{atom(), atom(), [_]}]) -> [_].
+-spec parallel_eval(FuncCalls) -> ResL when
+ FuncCalls :: [{Module, Function, Args}],
+ Module :: module(),
+ Function :: atom(),
+ Args :: [term()],
+ ResL :: [term()].
parallel_eval(ArgL) ->
Nodes = [node() | nodes()],
@@ -599,7 +724,13 @@ map_nodes([{M,F,A}|Tail],[Node|MoreNodes], Original) ->
%% Parallel version of lists:map/3 with exactly the same
%% arguments and return value as lists:map/3,
%% except that it calls exit/1 if a network error occurs.
--spec pmap({atom(),atom()}, [term()], [term()]) -> [term()].
+-spec pmap(FuncSpec, ExtraArgs, List1) -> List2 when
+ FuncSpec :: {Module,Function},
+ Module :: module(),
+ Function :: atom(),
+ ExtraArgs :: [term()],
+ List1 :: [Elem :: term()],
+ List2 :: [term()].
pmap({M,F}, As, List) ->
check(parallel_eval(build_args(M,F,As, List, [])), []).
@@ -616,15 +747,20 @@ check([], Ack) -> Ack.
%% location transparent version of process_info
--spec pinfo(pid()) -> [{atom(), _}] | 'undefined'.
+-spec pinfo(Pid) -> [{Item, Info}] | undefined when
+ Pid :: pid(),
+ Item :: atom(),
+ Info :: term().
pinfo(Pid) when node(Pid) =:= node() ->
process_info(Pid);
pinfo(Pid) ->
call(node(Pid), erlang, process_info, [Pid]).
--spec pinfo(pid(), Item) -> {Item, _} | 'undefined' | []
- when is_subtype(Item, atom()).
+-spec pinfo(Pid, Item) -> {Item, Info} | undefined | [] when
+ Pid :: pid(),
+ Item :: atom(),
+ Info :: term().
pinfo(Pid, Item) when node(Pid) =:= node() ->
process_info(Pid, Item);
diff --git a/lib/kernel/src/seq_trace.erl b/lib/kernel/src/seq_trace.erl
index 78c3040f21..a90b7b07c8 100644
--- a/lib/kernel/src/seq_trace.erl
+++ b/lib/kernel/src/seq_trace.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -38,15 +38,17 @@
-type flag() :: 'send' | 'receive' | 'print' | 'timestamp'.
-type component() :: 'label' | 'serial' | flag().
--type value() :: non_neg_integer()
- | {non_neg_integer(), non_neg_integer()}
- | boolean().
--type token_pair() :: {component(), value()}.
+-type value() :: (Integer :: non_neg_integer())
+ | {Previous :: non_neg_integer(),
+ Current :: non_neg_integer()}
+ | (Bool :: boolean()).
%%---------------------------------------------------------------------------
--type token() :: [] | {integer(), boolean(), _, _, _}.
--spec set_token(token()) -> token() | 'ok'.
+-type token() :: {integer(), boolean(), _, _, _}.
+-spec set_token(Token) -> PreviousToken | 'ok' when
+ Token :: [] | token(),
+ PreviousToken :: [] | token().
set_token([]) ->
erlang:seq_trace(sequential_trace_token,[]);
@@ -58,28 +60,35 @@ set_token({Flags,Label,Serial,_From,Lastcnt}) ->
%% expects that, the BIF can however "unofficially" handle atoms as well, and
%% atoms can be used if only Erlang nodes are involved
--spec set_token(component(), value()) -> token_pair().
+-spec set_token(Component, Val) -> {Component, OldVal} when
+ Component :: component(),
+ Val :: value(),
+ OldVal :: value().
set_token(Type, Val) ->
erlang:seq_trace(Type, Val).
--spec get_token() -> term().
+-spec get_token() -> [] | token().
get_token() ->
element(2,process_info(self(),sequential_trace_token)).
--spec get_token(component()) -> token_pair().
-
+-spec get_token(Component) -> {Component, Val} when
+ Component :: component(),
+ Val :: value().
get_token(Type) ->
erlang:seq_trace_info(Type).
--spec print(term()) -> 'ok'.
+-spec print(TraceInfo) -> 'ok' when
+ TraceInfo :: term().
print(Term) ->
erlang:seq_trace_print(Term),
ok.
--spec print(integer(), term()) -> 'ok'.
+-spec print(Label, TraceInfo) -> 'ok' when
+ Label :: integer(),
+ TraceInfo :: term().
print(Label, Term) when is_atom(Label) ->
erlang:error(badarg, [Label, Term]);
@@ -94,14 +103,17 @@ reset_trace() ->
%% reset_trace(Pid) -> % this might be a useful function too
--type tracer() :: pid() | port() | 'false'.
+-type tracer() :: (Pid :: pid()) | port() | 'false'.
--spec set_system_tracer(tracer()) -> tracer().
+-spec set_system_tracer(Tracer) -> OldTracer when
+ Tracer :: tracer(),
+ OldTracer :: tracer().
set_system_tracer(Pid) ->
erlang:system_flag(sequential_tracer, Pid).
--spec get_system_tracer() -> tracer().
+-spec get_system_tracer() -> Tracer when
+ Tracer :: tracer().
get_system_tracer() ->
element(2, erlang:system_info(sequential_tracer)).
diff --git a/lib/kernel/src/wrap_log_reader.erl b/lib/kernel/src/wrap_log_reader.erl
index fabaa07752..c41e0091e4 100644
--- a/lib/kernel/src/wrap_log_reader.erl
+++ b/lib/kernel/src/wrap_log_reader.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1998-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1998-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -41,6 +41,8 @@
first_no :: non_neg_integer() | 'one' % first read file number
}).
+-opaque continuation() :: #wrap_reader{}.
+
%%
%% Exported functions
%%
@@ -50,9 +52,11 @@
%% is not yet reached, we are on the first 'round' of filling the wrap
%% files.
--type open_ret() :: {'ok', #wrap_reader{}} | {'error', tuple()}.
+-type open_ret() :: {'ok', Continuation :: continuation()}
+ | {'error', Reason :: tuple()}.
--spec open(atom() | string()) -> open_ret().
+-spec open(Filename) -> open_ret() when
+ Filename :: string() | atom().
open(File) when is_atom(File) ->
open(atom_to_list(File));
@@ -77,7 +81,9 @@ open(File) when is_list(File) ->
Error
end.
--spec open(atom() | string(), integer()) -> open_ret().
+-spec open(Filename, N) -> open_ret() when
+ Filename :: string() | atom(),
+ N :: integer().
open(File, FileNo) when is_atom(File), is_integer(FileNo) ->
open(atom_to_list(File), FileNo);
@@ -100,22 +106,29 @@ open(File, FileNo) when is_list(File), is_integer(FileNo) ->
Error
end.
--spec close(#wrap_reader{}) -> 'ok' | {'error', atom()}.
+-spec close(Continuation) -> 'ok' | {'error', Reason} when
+ Continuation :: continuation(),
+ Reason :: file:posix().
close(#wrap_reader{fd = FD}) ->
file:close(FD).
--type chunk_ret() :: {#wrap_reader{}, [term()]}
- | {#wrap_reader{}, [term()], non_neg_integer()}
- | {#wrap_reader{}, 'eof'}
- | {'error', term()}.
+-type chunk_ret() :: {Continuation2, Terms :: [term()]}
+ | {Continuation2,
+ Terms :: [term()],
+ Badbytes :: non_neg_integer()}
+ | {Continuation2, 'eof'}
+ | {'error', Reason :: term()}.
--spec chunk(#wrap_reader{}) -> chunk_ret().
+-spec chunk(Continuation) -> chunk_ret() when
+ Continuation :: continuation().
chunk(WR = #wrap_reader{}) ->
chunk(WR, ?MAX_CHUNK_SIZE, 0).
--spec chunk(#wrap_reader{}, 'infinity' | pos_integer()) -> chunk_ret().
+-spec chunk(Continuation, N) -> chunk_ret() when
+ Continuation :: continuation(),
+ N :: infinity | pos_integer().
chunk(WR = #wrap_reader{}, infinity) ->
chunk(WR, ?MAX_CHUNK_SIZE, 0);