diff options
Diffstat (limited to 'erts/emulator/test')
65 files changed, 1818 insertions, 484 deletions
diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 4d0c87bf12..08d2066da3 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -61,7 +61,7 @@ MODULES= \ exception_SUITE \ float_SUITE \ fun_SUITE \ - fun_r12_SUITE \ + fun_r13_SUITE \ gc_SUITE \ guard_SUITE \ hash_SUITE \ diff --git a/erts/emulator/test/a_SUITE_data/timer_driver.c b/erts/emulator/test/a_SUITE_data/timer_driver.c index ef4dcdf501..44be94e0f0 100644 --- a/erts/emulator/test/a_SUITE_data/timer_driver.c +++ b/erts/emulator/test/a_SUITE_data/timer_driver.c @@ -17,7 +17,9 @@ #define CANCELLED 4 static ErlDrvData timer_start(ErlDrvPort, char*); -static void timer_stop(ErlDrvData), timer_read(ErlDrvData, char*, int), timer(ErlDrvData); +static void timer_stop(ErlDrvData), + timer_read(ErlDrvData, char*, ErlDrvSizeT), + timer(ErlDrvData); static ErlDrvEntry timer_driver_entry = { @@ -33,6 +35,16 @@ static ErlDrvEntry timer_driver_entry = NULL, timer, NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -47,8 +59,9 @@ static ErlDrvData timer_start(ErlDrvPort port, char *buf) } /* set the timer, this is monitored from erlang measuring the time */ -static void timer_read(ErlDrvData port, char *buf, int len) +static void timer_read(ErlDrvData p, char *buf, ErlDrvSizeT len) { + ErlDrvPort port = (ErlDrvPort) p; char reply[1]; if (buf[0] == START_TIMER) { @@ -62,8 +75,9 @@ static void timer_read(ErlDrvData port, char *buf, int len) } } -static void timer_stop(ErlDrvData port) +static void timer_stop(ErlDrvData p) { + ErlDrvPort port = (ErlDrvPort) p; driver_cancel_timer(port); } diff --git a/erts/emulator/test/alloc_SUITE_data/allocator_test.h b/erts/emulator/test/alloc_SUITE_data/allocator_test.h index 8b34375980..cd4a91d34a 100644 --- a/erts/emulator/test/alloc_SUITE_data/allocator_test.h +++ b/erts/emulator/test/alloc_SUITE_data/allocator_test.h @@ -19,7 +19,7 @@ #ifndef ALLOCATOR_TEST_H__ #define ALLOCATOR_TEST_H__ -typedef unsigned long Ulong; +typedef ErlDrvUInt Ulong; #ifndef __WIN32__ Ulong erts_alc_test(Ulong, Ulong, Ulong, Ulong); diff --git a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c index 1e98844838..66971654a2 100644 --- a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c +++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c @@ -50,13 +50,32 @@ typedef struct { ErlDrvData testcase_drv_start(ErlDrvPort port, char *command); void testcase_drv_stop(ErlDrvData drv_data); -void testcase_drv_run(ErlDrvData drv_data, char *buf, int len); +void testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); static ErlDrvEntry testcase_drv_entry = { NULL, testcase_drv_start, testcase_drv_stop, - testcase_drv_run + testcase_drv_run, + NULL, + NULL, + "testcase_drv", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL }; @@ -92,7 +111,7 @@ testcase_drv_stop(ErlDrvData drv_data) } void -testcase_drv_run(ErlDrvData drv_data, char *buf, int len) +testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data; ErlDrvTermData result_atom; diff --git a/erts/emulator/test/big_SUITE.erl b/erts/emulator/test/big_SUITE.erl index 3487917677..413bd3bcae 100644 --- a/erts/emulator/test/big_SUITE.erl +++ b/erts/emulator/test/big_SUITE.erl @@ -26,7 +26,7 @@ shift_limit_1/1, powmod/1, system_limit/1, otp_6692/1]). %% Internal exports. --export([eval/1, funcall/2]). +-export([eval/1]). -export([init/3]). -export([fac/1, fib/1, pow/2, gcd/2, lcm/2]). @@ -162,12 +162,15 @@ multi_match([Node|Ns], Expr, Rs) -> multi_match([], _, Rs) -> Rs. eval(Expr) -> - Fun = {?MODULE,funcall}, - {value,V,_} = erl_eval:expr(Expr, [], Fun), %Applied arithmetic BIFs. - V = eval(Expr, Fun), %Real arithmetic instructions. - V. + LFH = fun(Name, As) -> apply(?MODULE, Name, As) end, + + %% Applied arithmetic BIFs. + {value,V,_} = erl_eval:expr(Expr, [], {value,LFH}), -funcall(F, As) -> apply(?MODULE, F, As). + %% Real arithmetic instructions. + V = eval(Expr, LFH), + + V. %% Like a subset of erl_eval:expr/3, but uses real arithmetic instructions instead of %% applying them (it does make a difference). diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl index fed5854112..d9fc876482 100644 --- a/erts/emulator/test/binary_SUITE.erl +++ b/erts/emulator/test/binary_SUITE.erl @@ -33,7 +33,6 @@ %% erlang:external_size/1 %% size(Binary) %% iolist_size/1 -%% concat_binary/1 %% split_binary/2 %% hash(Binary, N) %% phash(Binary, N) @@ -47,7 +46,7 @@ init_per_testcase/2, end_per_testcase/2, copy_terms/1, conversions/1, deep_lists/1, deep_bitstr_lists/1, bad_list_to_binary/1, bad_binary_to_list/1, - t_split_binary/1, bad_split/1, t_concat_binary/1, + t_split_binary/1, bad_split/1, terms/1, terms_float/1, external_size/1, t_iolist_size/1, t_hash/1, bad_size/1, @@ -68,7 +67,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}, all() -> [copy_terms, conversions, deep_lists, deep_bitstr_lists, - t_split_binary, bad_split, t_concat_binary, + t_split_binary, bad_split, bad_list_to_binary, bad_binary_to_list, terms, terms_float, external_size, t_iolist_size, bad_binary_to_term_2, safe_binary_to_term2, @@ -93,7 +92,6 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. - init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> Config. @@ -381,41 +379,6 @@ bad_split(Config) when is_list(Config) -> bad_split(Bin, Pos) -> {'EXIT',{badarg,_}} = (catch split_binary(Bin, Pos)). -%% Tests concat_binary/2 and size/1. - -t_concat_binary(suite) -> []; -t_concat_binary(Config) when is_list(Config) -> - test_concat([]), - - test_concat([[]]), - test_concat([[], []]), - test_concat([[], [], []]), - - test_concat([[1], []]), - test_concat([[], [2]]), - test_concat([[], [3], []]), - - test_concat([[1, 2, 3], [4, 5, 6, 7]]), - test_concat([[1, 2, 3], [4, 5, 6, 7], [9, 10]]), - - test_concat([lists:seq(0, 255), lists:duplicate(1024, $@), - lists:duplicate(2048, $a), - lists:duplicate(4000, $b)]), - ok. - -test_concat(Lists) -> - test_concat(Lists, 0, [], []). - -test_concat([List|Rest], Size, Combined, Binaries) -> - ?line Bin = list_to_binary(List), - ?line test_concat(Rest, Size+length(List), Combined++List, [Bin|Binaries]); -test_concat([], Size, Combined, Binaries0) -> - ?line Binaries = lists:reverse(Binaries0), - ?line Bin = concat_binary(Binaries), - ?line Size = size(Bin), - ?line Size = iolist_size(Bin), - ?line Combined = binary_to_list(Bin). - t_hash(doc) -> "Test hash/2 with different type of binaries."; t_hash(Config) when is_list(Config) -> test_hash([]), diff --git a/erts/emulator/test/bs_match_misc_SUITE.erl b/erts/emulator/test/bs_match_misc_SUITE.erl index b022f96740..15427661f3 100644 --- a/erts/emulator/test/bs_match_misc_SUITE.erl +++ b/erts/emulator/test/bs_match_misc_SUITE.erl @@ -23,7 +23,7 @@ bound_var/1,bound_tail/1,t_float/1,little_float/1,sean/1, kenneth/1,encode_binary/1,native/1,happi/1, size_var/1,wiger/1,x0_context/1,huge_float_field/1, - writable_binary_matched/1,otp_7198/1]). + writable_binary_matched/1,otp_7198/1,unordered_bindings/1]). -include_lib("test_server/include/test_server.hrl"). @@ -33,7 +33,7 @@ all() -> [bound_var, bound_tail, t_float, little_float, sean, kenneth, encode_binary, native, happi, size_var, wiger, x0_context, huge_float_field, writable_binary_matched, - otp_7198]. + otp_7198, unordered_bindings]. groups() -> []. @@ -553,5 +553,15 @@ otp_7198_scan(<<C, Rest/binary>>, TokAcc) when otp_7198_scan(Rest, [{'KEYWORD', C} | TokAcc]) end. +unordered_bindings(Config) when is_list(Config) -> + {<<1,2,3,4>>,<<42,42>>,<<3,3,3>>} = + unordered_bindings(4, 2, 3, <<1,2,3,4, 42,42, 3,3,3, 3>>), + ok. + +unordered_bindings(CompressedLength, HashSize, PadLength, T) -> + <<Content:CompressedLength/binary,Mac:HashSize/binary, + Padding:PadLength/binary,PadLength>> = T, + {Content,Mac,Padding}. + id(I) -> I. diff --git a/erts/emulator/test/bs_utf_SUITE.erl b/erts/emulator/test/bs_utf_SUITE.erl index 72c656c400..4ab7d674a6 100644 --- a/erts/emulator/test/bs_utf_SUITE.erl +++ b/erts/emulator/test/bs_utf_SUITE.erl @@ -64,8 +64,7 @@ end_per_group(_GroupName, Config) -> utf8_roundtrip(Config) when is_list(Config) -> ?line utf8_roundtrip(0, 16#D7FF), - ?line utf8_roundtrip(16#E000, 16#FFFD), - ?line utf8_roundtrip(16#10000, 16#10FFFF), + ?line utf8_roundtrip(16#E000, 16#10FFFF), ok. utf8_roundtrip(First, Last) when First =< Last -> @@ -91,8 +90,7 @@ utf16_roundtrip(Config) when is_list(Config) -> do_utf16_roundtrip(Fun) -> do_utf16_roundtrip(0, 16#D7FF, Fun), - do_utf16_roundtrip(16#E000, 16#FFFD, Fun), - do_utf16_roundtrip(16#10000, 16#10FFFF, Fun). + do_utf16_roundtrip(16#E000, 16#10FFFF, Fun). do_utf16_roundtrip(First, Last, Fun) when First =< Last -> Fun(First), @@ -129,8 +127,7 @@ utf32_roundtrip(Config) when is_list(Config) -> do_utf32_roundtrip(Fun) -> do_utf32_roundtrip(0, 16#D7FF, Fun), - do_utf32_roundtrip(16#E000, 16#FFFD, Fun), - do_utf32_roundtrip(16#10000, 16#10FFFF, Fun). + do_utf32_roundtrip(16#E000, 16#10FFFF, Fun). do_utf32_roundtrip(First, Last, Fun) when First =< Last -> Fun(First), @@ -158,7 +155,6 @@ utf32_little_roundtrip(Char) -> utf8_illegal_sequences(Config) when is_list(Config) -> ?line fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large. ?line fail_range(16#D800, 16#DFFF), %Reserved for UTF-16. - ?line fail_range(16#FFFE, 16#FFFF), %Non-characters. %% Illegal first character. ?line [fail(<<I,16#8F,16#8F,16#8F>>) || I <- lists:seq(16#80, 16#BF)], @@ -251,7 +247,6 @@ fail_1(_) -> ok. utf16_illegal_sequences(Config) when is_list(Config) -> ?line utf16_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large. ?line utf16_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16. - ?line utf16_fail_range(16#FFFE, 16#FFFF), %Non-characters. ?line lonely_hi_surrogate(16#D800, 16#DFFF), ?line leading_lo_surrogate(16#DC00, 16#DFFF), @@ -300,7 +295,6 @@ leading_lo_surrogate(_, _, _) -> ok. utf32_illegal_sequences(Config) when is_list(Config) -> ?line utf32_fail_range(16#10FFFF+1, 16#10FFFF+512), %Too large. ?line utf32_fail_range(16#D800, 16#DFFF), %Reserved for UTF-16. - ?line utf32_fail_range(16#FFFE, 16#FFFF), %Non-characters. ?line utf32_fail_range(-100, -1), ok. diff --git a/erts/emulator/test/busy_port_SUITE_data/busy_drv.c b/erts/emulator/test/busy_port_SUITE_data/busy_drv.c index 1273d610ba..75106d3757 100644 --- a/erts/emulator/test/busy_port_SUITE_data/busy_drv.c +++ b/erts/emulator/test/busy_port_SUITE_data/busy_drv.c @@ -11,7 +11,8 @@ #define YES 1 static ErlDrvData busy_start(ErlDrvPort, char*); -static void busy_stop(ErlDrvData), busy_from_erlang(ErlDrvData, char*, int); +static void busy_stop(ErlDrvData), + busy_from_erlang(ErlDrvData, char*, ErlDrvSizeT); ErlDrvEntry busy_driver_entry = { @@ -23,6 +24,20 @@ ErlDrvEntry busy_driver_entry = NULL, "busy_drv", NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -73,7 +88,7 @@ static void busy_stop(ErlDrvData port) } static void -busy_from_erlang(ErlDrvData port, char* buf, int count) +busy_from_erlang(ErlDrvData port, char* buf, ErlDrvSizeT count) { if ((ErlDrvPort)port == slave_port) { set_busy_port(slave_port, next_slave_state); diff --git a/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c b/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c index 35919da2d0..9f6bd310c6 100644 --- a/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c +++ b/erts/emulator/test/busy_port_SUITE_data/hs_busy_drv.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009. All Rights Reserved. + * Copyright Ericsson AB 2009-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 @@ -21,9 +21,9 @@ #include "erl_driver.h" ErlDrvData start(ErlDrvPort port, char *command); -void output(ErlDrvData drv_data, char *buf, int len); -int control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen); +void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); +ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); static ErlDrvEntry busy_drv_entry = { NULL /* init */, @@ -61,7 +61,7 @@ ErlDrvData start(ErlDrvPort port, char *command) return (ErlDrvData) port; } -void output(ErlDrvData drv_data, char *buf, int len) +void output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { int res; ErlDrvPort port = (ErlDrvPort) drv_data; @@ -76,8 +76,8 @@ void output(ErlDrvData drv_data, char *buf, int len) driver_failure_atom(port, "driver_output_term failed"); } -int control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen) +ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { switch (command) { case 'B': /* busy */ diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl index 93fdc157f7..3e2bee06d1 100644 --- a/erts/emulator/test/call_trace_SUITE.erl +++ b/erts/emulator/test/call_trace_SUITE.erl @@ -934,6 +934,10 @@ exception_nocatch(Config) when is_list(Config) -> exception_nocatch(). exception_nocatch() -> + Deep4LocThrow = get_deep_4_loc({throw,[42]}), + Deep4LocError = get_deep_4_loc({error,[42]}), + Deep4LocBadmatch = get_deep_4_loc({'=',[a,b]}), + Prog = [{'_',[],[{exception_trace}]}], ?line 1 = erlang:trace_pattern({?MODULE,deep_1,'_'}, Prog), ?line 1 = erlang:trace_pattern({?MODULE,deep_2,'_'}, Prog), @@ -959,8 +963,9 @@ exception_nocatch() -> {trace,t2,exception_from,{erlang,throw,1}, {error,{nocatch,Q2}}}], exception_from, {error,{nocatch,Q2}}), - ?line expect({trace,T2,exit,{{nocatch,Q2},[{erlang,throw,[Q2]}, - {?MODULE,deep_4,1}]}}), + ?line expect({trace,T2,exit,{{nocatch,Q2},[{erlang,throw,[Q2],[]}, + {?MODULE,deep_4,1, + Deep4LocThrow}]}}), ?line Q3 = {dump,[dump,{dump}]}, ?line T3 = exception_nocatch(?LINE, error, [Q3], 4, @@ -968,18 +973,29 @@ exception_nocatch() -> {trace,t3,exception_from,{erlang,error,1}, {error,Q3}}], exception_from, {error,Q3}), - ?line expect({trace,T3,exit,{Q3,[{erlang,error,[Q3]}, - {?MODULE,deep_4,1}]}}), + ?line expect({trace,T3,exit,{Q3,[{erlang,error,[Q3],[]}, + {?MODULE,deep_4,1,Deep4LocError}]}}), ?line T4 = exception_nocatch(?LINE, '=', [17,4711], 5, [], exception_from, {error,{badmatch,4711}}), - ?line expect({trace,T4,exit,{{badmatch,4711},[{?MODULE,deep_4,1}]}}), + ?line expect({trace,T4,exit,{{badmatch,4711}, + [{?MODULE,deep_4,1,Deep4LocBadmatch}]}}), %% ?line erlang:trace_pattern({?MODULE,'_','_'}, false), ?line erlang:trace_pattern({erlang,'_','_'}, false), ?line expect(), ?line ok. +get_deep_4_loc(Arg) -> + try + deep_4(Arg), + ?t:fail(should_not_return_to_here) + catch + _:_ -> + [{?MODULE,deep_4,1,Loc0}|_] = erlang:get_stacktrace(), + Loc0 + end. + exception_nocatch(Line, B, Q, N, Extra, Tag, R) -> ?line io:format("== Subtest: ~w", [Line]), ?line Go = make_ref(), diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 29cbdedd17..25ce94096f 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -20,30 +20,34 @@ -module(code_SUITE). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, - new_binary_types/1, + versions/1,new_binary_types/1, t_check_process_code/1,t_check_old_code/1, t_check_process_code_ets/1, external_fun/1,get_chunk/1,module_md5/1,make_stub/1, - make_stub_many_funs/1,constant_pools/1, - false_dependency/1,coverage/1]). + make_stub_many_funs/1,constant_pools/1,constant_refc_binaries/1, + false_dependency/1,coverage/1,fun_confusion/1]). +-define(line_trace, 1). -include_lib("test_server/include/test_server.hrl"). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [new_binary_types, t_check_process_code, + [versions, new_binary_types, t_check_process_code, t_check_process_code_ets, t_check_old_code, external_fun, get_chunk, module_md5, make_stub, make_stub_many_funs, - constant_pools, false_dependency, coverage]. + constant_pools, constant_refc_binaries, false_dependency, + coverage, fun_confusion]. groups() -> []. init_per_suite(Config) -> + erts_debug:set_internal_state(available_internal_state, true), Config. end_per_suite(_Config) -> + catch erts_debug:set_internal_state(available_internal_state, false), ok. init_per_group(_GroupName, Config) -> @@ -52,6 +56,60 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +%% Make sure that only two versions of a module can be loaded. +versions(Config) when is_list(Config) -> + V1 = compile_version(1, Config), + V2 = compile_version(2, Config), + V3 = compile_version(3, Config), + + {ok,P1,1} = load_version(V1, 1), + {ok,P2,2} = load_version(V2, 2), + {error,not_purged} = load_version(V2, 2), + {error,not_purged} = load_version(V3, 3), + + 1 = check_version(P1), + 2 = check_version(P2), + 2 = versions:version(), + + %% Kill processes, unload code. + P1 ! P2 ! done, + _ = monitor(process, P1), + _ = monitor(process, P2), + receive + {'DOWN',_,process,P1,normal} -> ok + end, + receive + {'DOWN',_,process,P2,normal} -> ok + end, + true = erlang:purge_module(versions), + true = erlang:delete_module(versions), + true = erlang:purge_module(versions), + ok. + +compile_version(Version, Config) -> + Data = ?config(data_dir, Config), + File = filename:join(Data, "versions"), + {ok,versions,Bin} = compile:file(File, [{d,'VERSION',Version}, + binary,report]), + Bin. + +load_version(Code, Ver) -> + case erlang:load_module(versions, Code) of + {module,versions} -> + Pid = spawn_link(versions, loop, []), + Ver = versions:version(), + Ver = check_version(Pid), + {ok,Pid,Ver}; + Error -> + Error + end. + +check_version(Pid) -> + Pid ! {self(),version}, + receive + {Pid,version,Version} -> + Version + end. new_binary_types(Config) when is_list(Config) -> ?line Data = ?config(data_dir, Config), @@ -278,7 +336,8 @@ t_check_old_code(Config) when is_list(Config) -> external_fun(Config) when is_list(Config) -> ?line false = erlang:function_exported(another_code_test, x, 1), - ?line ExtFun = erlang:make_fun(id(another_code_test), x, 1), + AnotherCodeTest = id(another_code_test), + ExtFun = fun AnotherCodeTest:x/1, ?line {'EXIT',{undef,_}} = (catch ExtFun(answer)), ?line false = erlang:function_exported(another_code_test, x, 1), ?line false = lists:member(another_code_test, erlang:loaded()), @@ -403,7 +462,7 @@ make_stub_many_funs(Config) when is_list(Config) -> constant_pools(Config) when is_list(Config) -> ?line Data = ?config(data_dir, Config), ?line File = filename:join(Data, "literals"), - ?line {ok,literals,Code} = compile:file(File, [report,binary,constant_pool]), + ?line {ok,literals,Code} = compile:file(File, [report,binary]), ?line {module,literals} = erlang:load_module(literals, make_sub_binary(Code)), @@ -474,6 +533,131 @@ create_old_heap() -> create_old_heap() end. +constant_refc_binaries(Config) when is_list(Config) -> + wait_for_memory_deallocations(), + Bef = memory_binary(), + io:format("Binary data (bytes) before test: ~p\n", [Bef]), + + %% Compile the the literals module. + Data = ?config(data_dir, Config), + File = filename:join(Data, "literals"), + {ok,literals,Code} = compile:file(File, [report,binary]), + + %% Load the code and make sure that the binary is a refc binary. + {module,literals} = erlang:load_module(literals, Code), + Bin = literals:binary(), + Sz = byte_size(Bin), + Check = erlang:md5(Bin), + io:format("Size of literal refc binary: ~p\n", [Sz]), + {refc_binary,Sz,_,_} = erts_debug:get_internal_state({binary_info,Bin}), + true = erlang:delete_module(literals), + false = erlang:check_process_code(self(), literals), + true = erlang:purge_module(literals), + + %% Now try to provoke a memory leak. + provoke_mem_leak(10, Code, Check), + + %% Calculate the change in allocated binary data. + erlang:garbage_collect(), + wait_for_memory_deallocations(), + Aft = memory_binary(), + io:format("Binary data (bytes) after test: ~p", [Aft]), + Diff = Aft - Bef, + if + Diff < 0 -> + io:format("~p less bytes", [abs(Diff)]); + Diff > 0 -> + io:format("~p more bytes", [Diff]); + true -> + ok + end, + + %% Test for leaks. We must accept some natural variations in + %% the size of allocated binaries. + if + Diff > 64*1024 -> + ?t:fail(binary_leak); + true -> + ok + end. + +memory_binary() -> + try + erlang:memory(binary) + catch + error:notsup -> + 0 + end. + +provoke_mem_leak(0, _, _) -> ok; +provoke_mem_leak(N, Code, Check) -> + {module,literals} = erlang:load_module(literals, Code), + + %% Create several processes with references to the literal binary. + Self = self(), + Pids = [spawn_link(fun() -> + create_binaries(Self, NumRefs, Check) + end) || NumRefs <- lists:seq(1, 10)], + [receive {started,Pid} -> ok end || Pid <- Pids], + + %% Make the code old and remove references to the constant pool + %% in all processes. + true = erlang:delete_module(literals), + Ms = [spawn_monitor(fun() -> + false = erlang:check_process_code(Pid, literals) + end) || Pid <- Pids], + [receive + {'DOWN',R,process,P,normal} -> + ok + end || {P,R} <- Ms], + + %% Purge the code. + true = erlang:purge_module(literals), + + %% Tell the processes that the code has been purged. + [begin + monitor(process, Pid), + Pid ! purged + end || Pid <- Pids], + + %% Wait for all processes to terminate. + [receive + {'DOWN',_,process,Pid,normal} -> + ok + end || Pid <- Pids], + + %% We now expect that the binary has been deallocated. + provoke_mem_leak(N-1, Code, Check). + +create_binaries(Parent, NumRefs, Check) -> + Bin = literals:binary(), + Bins = lists:duplicate(NumRefs, Bin), + {bits,Bits} = literals:bits(), + Parent ! {started,self()}, + receive + purged -> + %% The code has been purged. Now make sure that + %% the binaries haven't been corrupted. + Check = erlang:md5(Bin), + [Bin = B || B <- Bins], + <<42:13,Bin/binary>> = Bits, + + %% Remove all references to the binaries + %% Doing it explicitly like this ensures that + %% the binaries are gone when the parent process + %% receives the 'DOWN' message. + erlang:garbage_collect() + end. + +wait_for_memory_deallocations() -> + try + erts_debug:set_internal_state(wait, deallocations) + catch + error:undef -> + erts_debug:set_internal_state(available_internal_state, true), + wait_for_memory_deallocations() + end. + %% OTP-7559: c_p->cp could contain garbage and create a false dependency %% to a module in a process. (Thanks to Richard Carlsson.) false_dependency(Config) when is_list(Config) -> @@ -555,6 +739,30 @@ coverage(Config) when is_list(Config) -> ?line {'EXIT',{badarg,_}} = (catch erlang:module_loaded(42)), ok. +fun_confusion(Config) when is_list(Config) -> + Data = ?config(data_dir, Config), + Src = filename:join(Data, "fun_confusion"), + Mod = fun_confusion, + + %% Load first version of module. + compile_load(Mod, Src, 1), + F1 = Mod:f(), + 1 = F1(), + + %% Load second version of module. + compile_load(Mod, Src, 2), + F2 = Mod:f(), + + %% F1 should refer to the old code, not the newly loaded code. + 1 = F1(), + 2 = F2(), + ok. + +compile_load(Mod, Src, Ver) -> + {ok,Mod,Code1} = compile:file(Src, [binary,{d,version,Ver}]), + {module,Mod} = code:load_binary(Mod, "fun_confusion.beam", Code1), + ok. + %% Utilities. make_sub_binary(Bin) when is_binary(Bin) -> diff --git a/erts/emulator/test/code_SUITE_data/fun_confusion.erl b/erts/emulator/test/code_SUITE_data/fun_confusion.erl new file mode 100644 index 0000000000..16000861df --- /dev/null +++ b/erts/emulator/test/code_SUITE_data/fun_confusion.erl @@ -0,0 +1,31 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 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 +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(fun_confusion). + +-export([f/0]). + +f() -> + fun() -> version() end. + +version() -> + %% Changing the value returned here should change + %% the identity of the fun in f/0. + ?version. + diff --git a/erts/emulator/test/code_SUITE_data/literals.erl b/erts/emulator/test/code_SUITE_data/literals.erl index 9f99b1a780..658427095e 100644 --- a/erts/emulator/test/code_SUITE_data/literals.erl +++ b/erts/emulator/test/code_SUITE_data/literals.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2009. 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 @@ -18,7 +18,7 @@ %% -module(literals). --export([a/0,b/0,huge_bignum/0]). +-export([a/0,b/0,huge_bignum/0,binary/0,unused_binaries/0,bits/0]). a() -> {a,42.0,[7,38877938333399637266518333334747]}. @@ -81,3 +81,22 @@ b() -> huge_bignum() -> 36#9987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR0737376766798779987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987779JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR0737376766798779987333333392789234879423987243987423432879423879234897423879423874328794323248423872348742323487423987423879243872347824374238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR07373767667987769707660766789076874238792437842374283926276478623462342363243SDKJFSDLEFHDSHJFE48H3838973879JFSDKJLFASLKJVBJKLEJKLDYEIOEHFEOU39873487SFHJSLDFASUIDFHSDHFEYR0R987YDFHDHFDLKHFSIDFHSIDFSIFDHSIFHWIHR073737676679877. + +-define(TIMES_FOUR(X), X,X,X,X). +-define(BYTES_256, 0:256,1:256,2:256,3:256, 4:256,5:256,6:256,7:256). +-define(KB_1, ?TIMES_FOUR(?BYTES_256)). +-define(KB_4, ?TIMES_FOUR(?KB_1)). +-define(KB_16, ?TIMES_FOUR(?KB_4)). +-define(KB_64, ?TIMES_FOUR(?KB_16)). +-define(KB_128, ?TIMES_FOUR(?KB_64)). +-define(MB_1, ?TIMES_FOUR(?KB_128)). + +binary() -> + %% Too big to be a heap binary. + <<?MB_1>>. + +unused_binaries() -> + {<<?KB_128>>,<<?BYTES_256>>}. + +bits() -> + {bits,<<42:13,?MB_1>>}. diff --git a/erts/emulator/test/code_SUITE_data/versions.erl b/erts/emulator/test/code_SUITE_data/versions.erl new file mode 100644 index 0000000000..7a6fd8847d --- /dev/null +++ b/erts/emulator/test/code_SUITE_data/versions.erl @@ -0,0 +1,33 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 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 +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(versions). +-export([loop/0,version/0]). + +loop() -> + receive + {Pid,version} -> + Pid ! {self(),version,version()}, + loop(); + done -> + ok + end. + +version() -> + ?VERSION. diff --git a/erts/emulator/test/ddll_SUITE_data/dummy_drv.c b/erts/emulator/test/ddll_SUITE_data/dummy_drv.c index e0d5067743..86f2abf1b1 100644 --- a/erts/emulator/test/ddll_SUITE_data/dummy_drv.c +++ b/erts/emulator/test/ddll_SUITE_data/dummy_drv.c @@ -7,7 +7,7 @@ static ErlDrvPort erlang_port; static ErlDrvData dummy_start(ErlDrvPort, char*); -static void dummy_read(ErlDrvData port, char *buf, int count); +static void dummy_read(ErlDrvData port, char *buf, ErlDrvSizeT count); static void dummy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int); static ErlDrvEntry dummy_driver_entry = { @@ -18,6 +18,21 @@ static ErlDrvEntry dummy_driver_entry = { NULL, NULL, "dummy_drv", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -37,7 +52,7 @@ static ErlDrvData dummy_start(ErlDrvPort port,char *buf) return (ErlDrvData)port; } -static void dummy_read(ErlDrvData port, char *buf, int count) +static void dummy_read(ErlDrvData port, char *buf, ErlDrvSizeT count) { driver_output(erlang_port, buf, count); } diff --git a/erts/emulator/test/ddll_SUITE_data/echo_drv.c b/erts/emulator/test/ddll_SUITE_data/echo_drv.c index edf78a979d..2b3510c641 100644 --- a/erts/emulator/test/ddll_SUITE_data/echo_drv.c +++ b/erts/emulator/test/ddll_SUITE_data/echo_drv.c @@ -3,9 +3,10 @@ static ErlDrvPort erlang_port; static ErlDrvData echo_start(ErlDrvPort, char *); -static void from_erlang(ErlDrvData, char*, int); -static int echo_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags); +static void from_erlang(ErlDrvData, char*, ErlDrvSizeT); +static ErlDrvSSizeT echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, unsigned *ret_flags); static ErlDrvEntry echo_driver_entry = { NULL, /* Init */ echo_start, @@ -21,7 +22,15 @@ static ErlDrvEntry echo_driver_entry = { NULL, NULL, NULL, - echo_call + echo_call, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL }; DRIVER_INIT(echo_drv) @@ -36,14 +45,15 @@ echo_start(ErlDrvPort port, char *buf) } static void -from_erlang(ErlDrvData data, char *buf, int count) +from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count) { driver_output((ErlDrvPort) data, buf, count); } -static int -echo_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags) +static ErlDrvSSizeT +echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, + unsigned *ret_flags) { *rbuf = buf; *ret_flags |= DRIVER_CALL_KEEP_BUFFER; diff --git a/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c b/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c index 3b2a44d907..26aa03a012 100644 --- a/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c +++ b/erts/emulator/test/ddll_SUITE_data/echo_drv_fail_init.c @@ -3,9 +3,10 @@ static ErlDrvPort erlang_port; static ErlDrvData echo_start(ErlDrvPort, char *); -static void from_erlang(ErlDrvData, char*, int); -static int echo_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags); +static void from_erlang(ErlDrvData, char*, ErlDrvSizeT); +static ErlDrvSSizeT echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, unsigned *ret_flags); static int echo_failing_init(void); static ErlDrvEntry echo_driver_entry = { @@ -23,7 +24,15 @@ static ErlDrvEntry echo_driver_entry = { NULL, NULL, NULL, - echo_call + echo_call, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL }; DRIVER_INIT(echo_drv) @@ -43,14 +52,15 @@ echo_start(ErlDrvPort port, char *buf) } static void -from_erlang(ErlDrvData data, char *buf, int count) +from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count) { driver_output((ErlDrvPort) data, buf, count); } -static int -echo_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags) +static ErlDrvSSizeT +echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, + unsigned *ret_flags) { *rbuf = buf; *ret_flags |= DRIVER_CALL_KEEP_BUFFER; diff --git a/erts/emulator/test/ddll_SUITE_data/initfail_drv.c b/erts/emulator/test/ddll_SUITE_data/initfail_drv.c index b676ff5121..ad241b9c4f 100644 --- a/erts/emulator/test/ddll_SUITE_data/initfail_drv.c +++ b/erts/emulator/test/ddll_SUITE_data/initfail_drv.c @@ -3,7 +3,7 @@ static ErlDrvPort erlang_port; static ErlDrvData easy_start(ErlDrvPort, char*); -static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int); +static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, ErlDrvSizeT); static ErlDrvEntry easy_driver_entry = { @@ -14,6 +14,21 @@ static ErlDrvEntry easy_driver_entry = NULL, NULL, "easy", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -34,7 +49,7 @@ static ErlDrvData easy_start(ErlDrvPort port, char *buf) return (ErlDrvData)port; } -static void easy_read(ErlDrvData port, char *buf, int count) +static void easy_read(ErlDrvData port, char *buf, ErlDrvSizeT count) { driver_output(erlang_port, buf, count); } diff --git a/erts/emulator/test/ddll_SUITE_data/lock_drv.c b/erts/emulator/test/ddll_SUITE_data/lock_drv.c index 2ec8fa3a29..d2605c5bfc 100644 --- a/erts/emulator/test/ddll_SUITE_data/lock_drv.c +++ b/erts/emulator/test/ddll_SUITE_data/lock_drv.c @@ -3,9 +3,10 @@ static ErlDrvPort erlang_port; static ErlDrvData echo_start(ErlDrvPort, char *); -static void from_erlang(ErlDrvData, char*, int); -static int echo_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags); +static void from_erlang(ErlDrvData, char*, ErlDrvSizeT); +static ErlDrvSSizeT echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, unsigned *ret_flags); static ErlDrvEntry echo_driver_entry = { NULL, /* Init */ echo_start, @@ -21,7 +22,15 @@ static ErlDrvEntry echo_driver_entry = { NULL, NULL, NULL, - echo_call + echo_call, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL }; DRIVER_INIT(echo_drv) @@ -37,14 +46,15 @@ echo_start(ErlDrvPort port, char *buf) } static void -from_erlang(ErlDrvData data, char *buf, int count) +from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count) { driver_output((ErlDrvPort) data, buf, count); } -static int -echo_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags) +static ErlDrvSSizeT +echo_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, + unsigned *ret_flags) { ErlDrvPort port = (ErlDrvPort) drv_data; driver_lock_driver(port); diff --git a/erts/emulator/test/ddll_SUITE_data/noinit_drv.c b/erts/emulator/test/ddll_SUITE_data/noinit_drv.c index 931386a305..5abf5c4dc6 100644 --- a/erts/emulator/test/ddll_SUITE_data/noinit_drv.c +++ b/erts/emulator/test/ddll_SUITE_data/noinit_drv.c @@ -3,7 +3,7 @@ static ErlDrvPort erlang_port; static ErlDrvData easy_start(ErlDrvPort, char*); -static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int); +static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, ErlDrvSizeT); static ErlDrvEntry easy_driver_entry = { @@ -14,6 +14,21 @@ static ErlDrvEntry easy_driver_entry = NULL, NULL, "easy", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -28,7 +43,7 @@ DRIVER_INIT(noinit_drv) /* * Provoke an error when loading the module. */ -int no_driver_init(void *handle) +ErlDrvEntry* no_driver_init(void *handle) #endif { erlang_port = (ErlDrvPort)-1; @@ -46,7 +61,7 @@ static ErlDrvData easy_start(ErlDrvPort port,char *buf) return (ErlDrvData)port; } -static void easy_read(ErlDrvData port, char *buf, int count) +static void easy_read(ErlDrvData port, char *buf, ErlDrvSizeT count) { driver_output(erlang_port, buf, count); } diff --git a/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c b/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c index 3a35820ee7..ac7efa30de 100644 --- a/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c +++ b/erts/emulator/test/ddll_SUITE_data/wrongname_drv.c @@ -7,7 +7,7 @@ static ErlDrvPort erlang_port; static ErlDrvData easy_start(ErlDrvPort, char*); -static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, int); +static void easy_stop(ErlDrvData), easy_read(ErlDrvData, char*, ErlDrvSizeT); static ErlDrvEntry easy_driver_entry = { @@ -18,6 +18,21 @@ static ErlDrvEntry easy_driver_entry = NULL, NULL, "easy", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -38,7 +53,7 @@ static ErlDrvData easy_start(ErlDrvPort port,char *buf) return (ErlDrvData)port; } -static void easy_read(ErlDrvData port, char *buf, int count) +static void easy_read(ErlDrvData port, char *buf, ErlDrvSizeT count) { driver_output(erlang_port, buf, count); } diff --git a/erts/emulator/test/decode_packet_SUITE.erl b/erts/emulator/test/decode_packet_SUITE.erl index c0499554eb..4acbe8c6e0 100644 --- a/erts/emulator/test/decode_packet_SUITE.erl +++ b/erts/emulator/test/decode_packet_SUITE.erl @@ -26,12 +26,14 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2,end_per_testcase/2, - basic/1, packet_size/1, neg/1, http/1, line/1, ssl/1, otp_8536/1]). + basic/1, packet_size/1, neg/1, http/1, line/1, ssl/1, otp_8536/1, + otp_9389/1, otp_9389_line/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [basic, packet_size, neg, http, line, ssl, otp_8536]. + [basic, packet_size, neg, http, line, ssl, otp_8536, + otp_9389, otp_9389_line]. groups() -> []. @@ -251,6 +253,28 @@ packet_size(Config) when is_list(Config) -> ?line {error,_} = decode_pkt(4,<<Size:32,Packet/binary>>) end, lists:seq(-10,-1)), + + %% Test OTP-9389, long HTTP header lines. + Opts = [{packet_size, 128}], + Pkt = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /", + string:chars($Y, 64), "\r\n\r\n"]), + <<Pkt1:50/binary, Pkt2/binary>> = Pkt, + ?line {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest1} = + erlang:decode_packet(http, Pkt1, Opts), + ?line {ok, {http_header,_,'Host',_,"localhost"}, Rest2} = + erlang:decode_packet(httph, Rest1, Opts), + ?line {more, undefined} = erlang:decode_packet(httph, Rest2, Opts), + ?line {ok, {http_header,_,"Link",_,_}, _} = + erlang:decode_packet(httph, list_to_binary([Rest2, Pkt2]), Opts), + + Pkt3 = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /", + string:chars($Y, 129), "\r\n\r\n"]), + ?line {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest3} = + erlang:decode_packet(http, Pkt3, Opts), + ?line {ok, {http_header,_,'Host',_,"localhost"}, Rest4} = + erlang:decode_packet(httph, Rest3, Opts), + ?line {error, invalid} = erlang:decode_packet(httph, Rest4, Opts), + ok. @@ -557,3 +581,35 @@ decode_pkt(Type,Bin,Opts) -> %%io:format(" -> ~p\n",[Res]), Res. +otp_9389(doc) -> ["Verify line_length works correctly for HTTP headers"]; +otp_9389(suite) -> []; +otp_9389(Config) when is_list(Config) -> + Opts = [{packet_size, 16384}, {line_length, 3000}], + Pkt = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /", + string:chars($X, 8192), + "\r\nContent-Length: 0\r\n\r\n"]), + <<Pkt1:5000/binary, Pkt2/binary>> = Pkt, + {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest1} = + erlang:decode_packet(http, Pkt1, Opts), + {ok, {http_header,_,'Host',_,"localhost"}, Rest2} = + erlang:decode_packet(httph, Rest1, Opts), + {more, undefined} = erlang:decode_packet(httph, Rest2, Opts), + {ok, {http_header,_,"Link",_,Link}, Rest3} = + erlang:decode_packet(httph, list_to_binary([Rest2, Pkt2]), Opts), + true = (length(Link) > 8000), + {ok, {http_header,_,'Content-Length',_,"0"}, <<"\r\n">>} = + erlang:decode_packet(httph, Rest3, Opts), + ok. + +otp_9389_line(doc) -> ["Verify packet_size works correctly for line mode"]; +otp_9389_line(suite) -> []; +otp_9389_line(Config) when is_list(Config) -> + Opts = [{packet_size, 20}], + Line1 = <<"0123456789012345678\n">>, + Line2 = <<"0123456789\n">>, + Line3 = <<"01234567890123456789\n">>, + Pkt = list_to_binary([Line1, Line2, Line3]), + ?line {ok, Line1, Rest1} = erlang:decode_packet(line, Pkt, Opts), + ?line {ok, Line2, Rest2} = erlang:decode_packet(line, Rest1, Opts), + ?line {error, invalid} = erlang:decode_packet(line, Rest2, Opts), + ok. diff --git a/erts/emulator/test/distribution_SUITE.erl b/erts/emulator/test/distribution_SUITE.erl index 19281f6d58..08308629fe 100644 --- a/erts/emulator/test/distribution_SUITE.erl +++ b/erts/emulator/test/distribution_SUITE.erl @@ -18,7 +18,7 @@ %% -module(distribution_SUITE). --compile(r12). +-compile(r13). %% Tests distribution and the tcp driver. @@ -37,7 +37,7 @@ dist_auto_connect_never/1, dist_auto_connect_once/1, dist_parallel_send/1, atom_roundtrip/1, - atom_roundtrip_r12b/1, + atom_roundtrip_r13b/1, contended_atom_cache_entry/1, bad_dist_structure/1, bad_dist_ext_receive/1, @@ -62,7 +62,7 @@ all() -> link_to_dead_new_node, applied_monitor_node, ref_port_roundtrip, nil_roundtrip, stop_dist, {group, trap_bif}, {group, dist_auto_connect}, - dist_parallel_send, atom_roundtrip, atom_roundtrip_r12b, + dist_parallel_send, atom_roundtrip, atom_roundtrip_r13b, contended_atom_cache_entry, bad_dist_structure, {group, bad_dist_ext}]. groups() -> @@ -1100,17 +1100,17 @@ atom_roundtrip(Config) when is_list(Config) -> ?line stop_node(Node), ?line ok. -atom_roundtrip_r12b(Config) when is_list(Config) -> - case ?t:is_release_available("r12b") of +atom_roundtrip_r13b(Config) when is_list(Config) -> + case ?t:is_release_available("r13b") of true -> ?line AtomData = atom_data(), ?line verify_atom_data(AtomData), - ?line {ok, Node} = start_node(Config, [], "r12b"), + ?line {ok, Node} = start_node(Config, [], "r13b"), ?line do_atom_roundtrip(Node, AtomData), ?line stop_node(Node), ?line ok; false -> - ?line {skip,"No OTP R12B available"} + ?line {skip,"No OTP R13B available"} end. do_atom_roundtrip(Node, AtomData) -> diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl index bcb0257ed1..643357263c 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -47,8 +47,8 @@ fd_change/1, steal_control/1, otp_6602/1, - 'driver_system_info_ver1.0'/1, - 'driver_system_info_ver1.1'/1, + driver_system_info_base_ver/1, + driver_system_info_prev_ver/1, driver_system_info_current_ver/1, driver_monitor/1, @@ -76,7 +76,8 @@ driver_select_use/1, thread_mseg_alloc_cache_clean/1, otp_9302/1, - thr_free_drv/1]). + thr_free_drv/1, + async_blast/1]). -export([bin_prefix/2]). @@ -134,8 +135,8 @@ all() -> [outputv_errors, outputv_echo, queue_echo, {group, timer}, driver_unloaded, io_ready_exit, use_fallback_pollset, bad_fd_in_pollset, driver_event, fd_change, - steal_control, otp_6602, 'driver_system_info_ver1.0', - 'driver_system_info_ver1.1', + steal_control, otp_6602, driver_system_info_base_ver, + driver_system_info_prev_ver, driver_system_info_current_ver, driver_monitor, {group, ioq_exit}, zero_extended_marker_garb_drv, invalid_extended_marker_drv, larger_major_vsn_drv, @@ -145,7 +146,8 @@ all() -> smp_select, driver_select_use, thread_mseg_alloc_cache_clean, otp_9302, - thr_free_drv]. + thr_free_drv, + async_blast]. groups() -> [{timer, [], @@ -1081,19 +1083,19 @@ otp_6602(Config) when is_list(Config) -> -define(EXPECTED_SYSTEM_INFO_NAMES, ?EXPECTED_SYSTEM_INFO_NAMES2). -'driver_system_info_ver1.0'(doc) -> +'driver_system_info_base_ver'(doc) -> []; -'driver_system_info_ver1.0'(suite) -> +'driver_system_info_base_ver'(suite) -> []; -'driver_system_info_ver1.0'(Config) when is_list(Config) -> - ?line driver_system_info_test(Config, sys_info_1_0_drv). +'driver_system_info_base_ver'(Config) when is_list(Config) -> + ?line driver_system_info_test(Config, sys_info_base_drv). -'driver_system_info_ver1.1'(doc) -> +'driver_system_info_prev_ver'(doc) -> []; -'driver_system_info_ver1.1'(suite) -> +'driver_system_info_prev_ver'(suite) -> []; -'driver_system_info_ver1.1'(Config) when is_list(Config) -> - ?line driver_system_info_test(Config, sys_info_1_1_drv). +'driver_system_info_prev_ver'(Config) when is_list(Config) -> + ?line driver_system_info_test(Config, sys_info_prev_drv). driver_system_info_current_ver(doc) -> []; @@ -1794,7 +1796,7 @@ driver_select_use0(Config) -> thread_mseg_alloc_cache_clean(Config) when is_list(Config) -> case {erlang:system_info(threads), - mseg_inst_info(0), + erlang:system_info({allocator,mseg_alloc}), driver_alloc_sbct()} of {_, false, _} -> ?line {skipped, "No mseg_alloc"}; @@ -1911,17 +1913,30 @@ otp_9302(Config) when is_list(Config) -> ?line port_command(Port, ""), ?line {msg, block} = get_port_msg(Port, infinity), ?line {msg, job} = get_port_msg(Port, infinity), - ?line case erlang:system_info(thread_pool_size) of - 0 -> - {msg, cancel} = get_port_msg(Port, infinity); - _ -> - ok - end, - ?line {msg, job} = get_port_msg(Port, infinity), + ?line C = case erlang:system_info(thread_pool_size) of + 0 -> + ?line {msg, cancel} = get_port_msg(Port, infinity), + ?line {msg, job} = get_port_msg(Port, infinity), + ?line false; + _ -> + case get_port_msg(Port, infinity) of + {msg, cancel} -> %% Cancel always fail in Rel >= 15 + ?line {msg, job} = get_port_msg(Port, infinity), + ?line false; + {msg, job} -> + ?line ok, + ?line true + end + end, ?line {msg, end_of_jobs} = get_port_msg(Port, infinity), ?line no_msg = get_port_msg(Port, 2000), ?line port_close(Port), - ?line ok. + ?line case C of + true -> + ?line {comment, "Async job cancelled"}; + false -> + ?line {comment, "Async job not cancelled"} + end. thr_free_drv(Config) when is_list(Config) -> ?line Path = ?config(data_dir, Config), @@ -1954,6 +1969,48 @@ thr_free_drv_control(Port, N) -> % io:format("N=~p, SID=~p", [N, erlang:system_info(scheduler_id)]), thr_free_drv_control(Port, N+1) end. + +async_blast(Config) when is_list(Config) -> + ?line Path = ?config(data_dir, Config), + ?line erl_ddll:start(), + ?line ok = load_driver(Path, async_blast_drv), + ?line SchedOnln = erlang:system_info(schedulers_online), + ?line MemBefore = driver_alloc_size(), + ?line Start = os:timestamp(), + ?line Blast = fun () -> + Port = open_port({spawn, async_blast_drv}, []), + true = is_port(Port), + port_command(Port, ""), + receive + {Port, done} -> + ok + end, + port_close(Port) + end, + ?line Ps = lists:map(fun (N) -> + spawn_opt(Blast, + [{scheduler, + (N rem SchedOnln)+ 1}, + monitor]) + end, + lists:seq(1, 100)), + ?line MemMid = driver_alloc_size(), + ?line lists:foreach(fun ({Pid, Mon}) -> + receive + {'DOWN',Mon,process,Pid,_} -> ok + end + end, Ps), + ?line End = os:timestamp(), + ?line MemAfter = driver_alloc_size(), + ?line io:format("MemBefore=~p, MemMid=~p, MemAfter=~p~n", + [MemBefore, MemMid, MemAfter]), + ?line AsyncBlastTime = timer:now_diff(End,Start)/1000000, + ?line io:format("AsyncBlastTime=~p~n", [AsyncBlastTime]), + ?line MemBefore = MemAfter, + ?line erlang:display({async_blast_time, AsyncBlastTime}), + ?line ok. + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Utilities @@ -2128,6 +2185,14 @@ wait_deallocations() -> end. driver_alloc_size() -> + case erlang:system_info(smp_support) of + true -> + ok; + false -> + %% driver_alloc also used by elements in lock-free queues, + %% give these some time to be deallocated... + receive after 100 -> ok end + end, wait_deallocations(), case erlang:system_info({allocator_sizes, driver_alloc}) of false -> diff --git a/erts/emulator/test/driver_SUITE_data/Makefile.src b/erts/emulator/test/driver_SUITE_data/Makefile.src index 62ab5169c0..9cc107cc66 100644 --- a/erts/emulator/test/driver_SUITE_data/Makefile.src +++ b/erts/emulator/test/driver_SUITE_data/Makefile.src @@ -13,10 +13,11 @@ MISC_DRVS = outputv_drv@dll@ \ missing_callback_drv@dll@ \ thr_alloc_drv@dll@ \ otp_9302_drv@dll@ \ - thr_free_drv@dll@ + thr_free_drv@dll@ \ + async_blast_drv@dll@ -SYS_INFO_DRVS = sys_info_1_0_drv@dll@ \ - sys_info_1_1_drv@dll@ \ +SYS_INFO_DRVS = sys_info_base_drv@dll@ \ + sys_info_prev_drv@dll@ \ sys_info_curr_drv@dll@ VSN_MISMATCH_DRVS = zero_extended_marker_garb_drv@dll@ \ diff --git a/erts/emulator/test/driver_SUITE_data/async_blast_drv.c b/erts/emulator/test/driver_SUITE_data/async_blast_drv.c new file mode 100644 index 0000000000..c2086c5860 --- /dev/null +++ b/erts/emulator/test/driver_SUITE_data/async_blast_drv.c @@ -0,0 +1,124 @@ +/* + * %CopyrightBegin% + * + * Copyright Ericsson AB 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 + * compliance with the License. You should have received a copy of the + * Erlang Public License along with this software. If not, it can be + * retrieved online at http://www.erlang.org/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * %CopyrightEnd% + */ + +#include "erl_driver.h" + +#define NO_ASYNC_JOBS 10000 + +static void stop(ErlDrvData drv_data); +static ErlDrvData start(ErlDrvPort port, + char *command); +static void output(ErlDrvData drv_data, + char *buf, ErlDrvSizeT len); +static void ready_async(ErlDrvData drv_data, + ErlDrvThreadData thread_data); + +static ErlDrvEntry async_blast_drv_entry = { + NULL /* init */, + start, + stop, + output, + NULL /* ready_input */, + NULL /* ready_output */, + "async_blast_drv", + NULL /* finish */, + NULL /* handle */, + NULL /* control */, + NULL /* timeout */, + NULL /* outputv */, + ready_async, + NULL /* flush */, + NULL /* call */, + NULL /* event */, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + ERL_DRV_FLAG_USE_PORT_LOCKING, + NULL /* handle2 */, + NULL /* handle_monitor */ +}; + +typedef struct { + ErlDrvPort port; + ErlDrvTermData caller; + int counter; +} async_blast_data_t; + + +DRIVER_INIT(async_blast_drv) +{ + return &async_blast_drv_entry; +} + +static void stop(ErlDrvData drv_data) +{ + driver_free((void *) drv_data); +} + +static ErlDrvData start(ErlDrvPort port, + char *command) +{ + async_blast_data_t *abd; + + abd = driver_alloc(sizeof(async_blast_data_t)); + if (!abd) + return ERL_DRV_ERROR_GENERAL; + + abd->port = port; + abd->counter = 0; + return (ErlDrvData) abd; +} + +static void async_invoke(void *data) +{ + +} +#include <stdio.h> + +static void ready_async(ErlDrvData drv_data, + ErlDrvThreadData thread_data) +{ + async_blast_data_t *abd = (async_blast_data_t *) drv_data; + if (--abd->counter == 0) { + ErlDrvTermData spec[] = { + ERL_DRV_PORT, driver_mk_port(abd->port), + ERL_DRV_ATOM, driver_mk_atom("done"), + ERL_DRV_TUPLE, 2 + }; + driver_send_term(abd->port, abd->caller, + spec, sizeof(spec)/sizeof(spec[0])); + } +} + +static void output(ErlDrvData drv_data, + char *buf, ErlDrvSizeT len) +{ + async_blast_data_t *abd = (async_blast_data_t *) drv_data; + if (abd->counter == 0) { + int i; + abd->caller = driver_caller(abd->port); + abd->counter = NO_ASYNC_JOBS; + for (i = 0; i < NO_ASYNC_JOBS; i++) { + if (0 > driver_async(abd->port, NULL, async_invoke, NULL, NULL)) { + driver_failure_atom(abd->port, "driver_async_failed"); + break; + } + } + } +} diff --git a/erts/emulator/test/driver_SUITE_data/caller_drv.c b/erts/emulator/test/driver_SUITE_data/caller_drv.c index a78d51966f..1ed20b0638 100644 --- a/erts/emulator/test/driver_SUITE_data/caller_drv.c +++ b/erts/emulator/test/driver_SUITE_data/caller_drv.c @@ -23,17 +23,17 @@ static ErlDrvData start(ErlDrvPort port, char *command); static void output(ErlDrvData drv_data, - char *buf, int len); + char *buf, ErlDrvSizeT len); static void outputv(ErlDrvData drv_data, ErlIOVec *ev); -static int control(ErlDrvData drv_data, - unsigned int command, char *buf, - int len, char **rbuf, int rlen); -static int call(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen, - unsigned int *flags); +static ErlDrvSSizeT control(ErlDrvData drv_data, + unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); +static ErlDrvSSizeT call(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, + unsigned int *flags); static ErlDrvEntry caller_drv_entry = { NULL /* init */, @@ -98,7 +98,7 @@ start(ErlDrvPort port, char *command) } static void -output(ErlDrvData drv_data, char *buf, int len) +output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { send_caller(drv_data, "output"); } @@ -109,20 +109,20 @@ outputv(ErlDrvData drv_data, ErlIOVec *ev) send_caller(drv_data, "outputv"); } -static int +static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen) + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { send_caller(drv_data, "control"); return 0; } -static int +static ErlDrvSSizeT call(ErlDrvData drv_data, unsigned int command, - char *buf, int len, - char **rbuf, int rlen, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, unsigned int *flags) { /* echo call */ diff --git a/erts/emulator/test/driver_SUITE_data/chkio_drv.c b/erts/emulator/test/driver_SUITE_data/chkio_drv.c index bbdb09cfcb..40f1ad4fea 100644 --- a/erts/emulator/test/driver_SUITE_data/chkio_drv.c +++ b/erts/emulator/test/driver_SUITE_data/chkio_drv.c @@ -141,8 +141,8 @@ static void chkio_drv_stop(ErlDrvData); static void chkio_drv_ready_input(ErlDrvData, ErlDrvEvent); static void chkio_drv_ready_output(ErlDrvData, ErlDrvEvent); static void chkio_drv_ready_event(ErlDrvData, ErlDrvEvent, ErlDrvEventData); -static int chkio_drv_control(ErlDrvData, unsigned int, - char *, int, char **, int); +static ErlDrvSSizeT chkio_drv_control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); static void chkio_drv_timeout(ErlDrvData); static void chkio_drv_stop_select(ErlDrvEvent, void*); @@ -188,7 +188,7 @@ stop_use_fallback_pollset(ChkioDrvData *cddp) for (i = 0; i < CHKIO_FALLBACK_FDS; i++) { if (cbdp->dev_null[i].fd >= 0) { if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->dev_null[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->dev_null[i].fd, DO_WRITE, 0) != 0) { fprintf(stderr, @@ -200,7 +200,7 @@ stop_use_fallback_pollset(ChkioDrvData *cddp) } if (cbdp->dev_zero[i].fd >= 0) { if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->dev_zero[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->dev_zero[i].fd, DO_READ, 0) != 0) { fprintf(stderr, @@ -212,7 +212,7 @@ stop_use_fallback_pollset(ChkioDrvData *cddp) } if (cbdp->pipe_in[i].fd >= 0) { if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->pipe_in[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->pipe_in[i].fd, DO_READ, 0) != 0) { fprintf(stderr, @@ -224,7 +224,7 @@ stop_use_fallback_pollset(ChkioDrvData *cddp) } if (cbdp->pipe_out[i].fd >= 0) { if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->pipe_out[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->pipe_out[i].fd, DO_WRITE, 0) != 0) { fprintf(stderr, @@ -249,11 +249,11 @@ stop_driver_event(ChkioDrvData *cddp) cddp->test_data = NULL; if (cdep->in_fd >= 0) { - driver_event(cddp->port, (ErlDrvEvent) cdep->in_fd, NULL); + driver_event(cddp->port, (ErlDrvEvent) (ErlDrvSInt) cdep->in_fd, NULL); close(cdep->in_fd); } if (cdep->out_fd >= 0) { - driver_event(cddp->port, (ErlDrvEvent) cdep->out_fd, NULL); + driver_event(cddp->port, (ErlDrvEvent) (ErlDrvSInt) cdep->out_fd, NULL); close(cdep->out_fd); } driver_free(cdep); @@ -268,7 +268,7 @@ stop_fd_change(ChkioDrvData *cddp) cddp->test_data = NULL; driver_cancel_timer(cddp->port); if (cfcp->fds[0] >= 0) { - driver_select(cddp->port, (ErlDrvEvent) cfcp->fds[0], DO_READ, 0); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) cfcp->fds[0], DO_READ, 0); close(cfcp->fds[0]); close(cfcp->fds[1]); } @@ -282,8 +282,8 @@ stop_bad_fd_in_pollset(ChkioDrvData *cddp) if (cddp->test_data) { ChkioBadFdInPollset *bfipp = (ChkioBadFdInPollset *) cddp->test_data; cddp->test_data = NULL; - driver_select(cddp->port, (ErlDrvEvent) bfipp->fds[0], DO_WRITE, 0); - driver_select(cddp->port, (ErlDrvEvent) bfipp->fds[1], DO_READ, 0); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) bfipp->fds[0], DO_WRITE, 0); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) bfipp->fds[1], DO_READ, 0); driver_free((void *) bfipp); } } @@ -296,21 +296,21 @@ stop_steal(ChkioDrvData *cddp) cddp->test_data = NULL; if (csp->driver_select_fds[0] >= 0) driver_select(cddp->port, - (ErlDrvEvent) csp->driver_select_fds[0], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_select_fds[0], DO_READ, 0); if (csp->driver_select_fds[1] >= 0) driver_select(cddp->port, - (ErlDrvEvent) csp->driver_select_fds[1], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_select_fds[1], DO_WRITE, 0); if (csp->driver_event_fds[0] >= 0) driver_event(cddp->port, - (ErlDrvEvent) csp->driver_event_fds[0], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_event_fds[0], NULL); if (csp->driver_event_fds[1] >= 0) driver_event(cddp->port, - (ErlDrvEvent) csp->driver_event_fds[1], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_event_fds[1], NULL); driver_free(csp); } @@ -353,7 +353,7 @@ static void free_smp_select(ChkioSmpSelect* pip, ErlDrvPort port) abort(); } case Selected: - driver_select(port, (ErlDrvEvent)pip->read_fd, DO_READ, 0); + driver_select(port, (ErlDrvEvent)(ErlDrvSInt)pip->read_fd, DO_READ, 0); /*fall through*/ case Opened: close(pip->read_fd); @@ -475,8 +475,8 @@ chkio_drv_stop(ErlDrvData drv_data) { fprintf(stderr, "%s:%d: Failed to open /dev/null\n", __FILE__, __LINE__); } - driver_select(cddp->port, (ErlDrvEvent) fd, DO_WRITE, 1); - driver_select(cddp->port, (ErlDrvEvent) fd, DO_WRITE, 0); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) fd, DO_WRITE, 1); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) fd, DO_WRITE, 0); close(fd); @@ -491,7 +491,7 @@ chkio_drv_ready_output(ErlDrvData drv_data, ErlDrvEvent event) { #ifdef UNIX ChkioDrvData *cddp = (ChkioDrvData *) drv_data; - int fd = (int) event; + int fd = (int) (ErlDrvSInt) event; switch (cddp->test) { case CHKIO_USE_FALLBACK_POLLSET: { @@ -533,7 +533,7 @@ chkio_drv_ready_input(ErlDrvData drv_data, ErlDrvEvent event) { #ifdef UNIX ChkioDrvData *cddp = (ChkioDrvData *) drv_data; - int fd = (int) event; + int fd = (int) (ErlDrvSInt) event; switch (cddp->test) { case CHKIO_USE_FALLBACK_POLLSET: { @@ -630,7 +630,7 @@ chkio_drv_ready_event(ErlDrvData drv_data, case CHKIO_DRIVER_EVENT: { #ifdef HAVE_POLL_H ChkioDriverEvent *cdep = cddp->test_data; - int fd = (int) event; + int fd = (int) (ErlDrvSInt) event; if (fd == cdep->in_fd) { if (event_data->events == POLLIN && event_data->revents == POLLIN) { @@ -679,7 +679,7 @@ chkio_drv_timeout(ErlDrvData drv_data) int in_fd = cfcp->fds[0]; int out_fd = cfcp->fds[1]; if (in_fd >= 0) { - if (driver_select(cddp->port, (ErlDrvEvent) in_fd, DO_READ, 0) < 0) + if (driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) in_fd, DO_READ, 0) < 0) driver_failure_atom(cddp->port, "deselect_failed"); (void) write(out_fd, (void *) "!", 1); close(out_fd); @@ -689,7 +689,7 @@ chkio_drv_timeout(ErlDrvData drv_data) driver_failure_posix(cddp->port, errno); } else { - if (driver_select(cddp->port, (ErlDrvEvent) cfcp->fds[0], + if (driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) cfcp->fds[0], DO_READ, 1) < 0) driver_failure_atom(cddp->port, "select_failed"); if (cfcp->fds[0] == in_fd) @@ -709,14 +709,14 @@ chkio_drv_timeout(ErlDrvData drv_data) #endif /* UNIX */ } -static int +static ErlDrvSSizeT chkio_drv_control(ErlDrvData drv_data, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { char *res_str; - int res_len = -1; + ErlDrvSSizeT res_len = -1; #ifndef UNIX #ifdef __WIN32__ res_str = "skip: windows_different"; @@ -854,7 +854,7 @@ chkio_drv_control(ErlDrvData drv_data, int fds[2]; cbdp->dev_null[i].fd = open("/dev/null", O_WRONLY); if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->dev_null[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->dev_null[i].fd, DO_WRITE, 1) != 0) { driver_failure_posix(cddp->port, errno); @@ -862,7 +862,7 @@ chkio_drv_control(ErlDrvData drv_data, } cbdp->dev_zero[i].fd = open("/dev/zero", O_RDONLY); if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->dev_zero[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->dev_zero[i].fd, DO_READ, 1) != 0) { driver_failure_posix(cddp->port, errno); @@ -873,7 +873,7 @@ chkio_drv_control(ErlDrvData drv_data, cbdp->pipe_in[i].fd = fds[0]; cbdp->pipe_out[i].fd = fds[1]; if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->pipe_in[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->pipe_in[i].fd, DO_READ, 1) != 0) { driver_failure_posix(cddp->port, EIO); @@ -882,7 +882,7 @@ chkio_drv_control(ErlDrvData drv_data, if (i % 2 == 0) (void) write(cbdp->pipe_out[i].fd, "!", 1); if (driver_select(cddp->port, - (ErlDrvEvent) cbdp->pipe_out[i].fd, + (ErlDrvEvent) (ErlDrvSInt) cbdp->pipe_out[i].fd, DO_WRITE, 1) != 0) { driver_failure_posix(cddp->port, EIO); @@ -928,8 +928,8 @@ chkio_drv_control(ErlDrvData drv_data, bfipp->fds[0] = fds[9]; bfipp->fds[1] = fds[10]; cddp->test_data = (void *) bfipp; - driver_select(cddp->port, (ErlDrvEvent) fds[9], DO_WRITE, 1); - driver_select(cddp->port, (ErlDrvEvent) fds[10], DO_READ, 1); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) fds[9], DO_WRITE, 1); + driver_select(cddp->port, (ErlDrvEvent) (ErlDrvSInt) fds[10], DO_READ, 1); } } res_str = "ok"; @@ -965,7 +965,7 @@ chkio_drv_control(ErlDrvData drv_data, cdep->in_ok = 0; res = driver_event(cddp->port, - (ErlDrvEvent) in_fd, + (ErlDrvEvent) (ErlDrvSInt) in_fd, &cdep->in_data); if (res < 0) { res_str = "skip: driver_event() not supported"; @@ -985,7 +985,7 @@ chkio_drv_control(ErlDrvData drv_data, cdep->out_ok = 0; res = driver_event(cddp->port, - (ErlDrvEvent) out_fd, + (ErlDrvEvent) (ErlDrvSInt) out_fd, &cdep->out_data); if (res < 0) { close(out_fd); @@ -1062,7 +1062,7 @@ chkio_drv_control(ErlDrvData drv_data, csp->event_data[0].events = POLLIN; csp->event_data[0].revents = 0; res = driver_event(cddp->port, - (ErlDrvEvent) csp->driver_event_fds[0], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_event_fds[0], &csp->event_data[0]); if (res < 0) driver_failure_atom(cddp->port, @@ -1071,7 +1071,7 @@ chkio_drv_control(ErlDrvData drv_data, csp->event_data[1].events = POLLOUT; csp->event_data[1].revents = 0; res = driver_event(cddp->port, - (ErlDrvEvent) csp->driver_event_fds[1], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_event_fds[1], &csp->event_data[1]); if (res < 0) driver_failure_atom(cddp->port, @@ -1083,7 +1083,7 @@ chkio_drv_control(ErlDrvData drv_data, /* Steal with driver_select() */ if (res >= 0) { res = driver_select(cddp->port, - (ErlDrvEvent) csp->driver_select_fds[0], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_select_fds[0], DO_READ, 1); if (res < 0) @@ -1092,7 +1092,7 @@ chkio_drv_control(ErlDrvData drv_data, } if (res >= 0) { res = driver_select(cddp->port, - (ErlDrvEvent) csp->driver_select_fds[1], + (ErlDrvEvent) (ErlDrvSInt) csp->driver_select_fds[1], DO_WRITE, 1); if (res < 0) @@ -1159,14 +1159,14 @@ chkio_drv_control(ErlDrvData drv_data, csap->driver_event_fds[1] = write_fds[1]; res = driver_select(cddp->port, - (ErlDrvEvent) csap->driver_select_fds[0], + (ErlDrvEvent) (ErlDrvSInt) csap->driver_select_fds[0], DO_READ, 1); if (res < 0) driver_failure_atom(cddp->port, "driver_select_failed"); if (res >= 0) { res = driver_select(cddp->port, - (ErlDrvEvent) csap->driver_select_fds[1], + (ErlDrvEvent) (ErlDrvSInt) csap->driver_select_fds[1], DO_WRITE, 1); if (res < 0) @@ -1177,7 +1177,7 @@ chkio_drv_control(ErlDrvData drv_data, csap->event_data[0].events = POLLIN; csap->event_data[0].revents = 0; res = driver_event(cddp->port, - (ErlDrvEvent) csap->driver_event_fds[0], + (ErlDrvEvent) (ErlDrvSInt) csap->driver_event_fds[0], &csap->event_data[0]); if (res < 0) { close(csap->driver_event_fds[0]); @@ -1190,7 +1190,7 @@ chkio_drv_control(ErlDrvData drv_data, csap->event_data[1].events = POLLOUT; csap->event_data[1].revents = 0; res = driver_event(cddp->port, - (ErlDrvEvent) csap->driver_event_fds[1], + (ErlDrvEvent) (ErlDrvSInt) csap->driver_event_fds[1], &csap->event_data[1]); if (res < 0) driver_failure_atom(cddp->port, @@ -1285,7 +1285,7 @@ chkio_drv_control(ErlDrvData drv_data, } else { TRACEF(("%T: Select on pipe [%d->%d]\n", cddp->id, pip->write_fd, pip->read_fd)); - if (driver_select(cddp->port, (ErlDrvEvent)pip->read_fd, DO_READ, 1)) { + if (driver_select(cddp->port, (ErlDrvEvent)(ErlDrvSInt)pip->read_fd, DO_READ, 1)) { fprintf(stderr, "driver_select failed for fd=%d\n", pip->read_fd); abort(); } @@ -1314,7 +1314,7 @@ chkio_drv_control(ErlDrvData drv_data, op >>= 1; if (op & 1) { TRACEF(("%T: Deselect on pipe [%d->%d]\n", cddp->id, pip->write_fd, pip->read_fd)); - if (driver_select(cddp->port, (ErlDrvEvent)pip->read_fd, DO_READ, 0)) { + if (driver_select(cddp->port, (ErlDrvEvent)(ErlDrvSInt)pip->read_fd, DO_READ, 0)) { fprintf(stderr, "driver_(de)select failed for fd=%d\n", pip->read_fd); abort(); } diff --git a/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c b/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c index 6afa46b3a2..e6a3edcd74 100644 --- a/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c +++ b/erts/emulator/test/driver_SUITE_data/io_ready_exit_drv.c @@ -40,8 +40,9 @@ static void io_ready_exit_ready_input(ErlDrvData, ErlDrvEvent); static void io_ready_exit_ready_output(ErlDrvData, ErlDrvEvent); static void io_ready_exit_drv_output(ErlDrvData, char *, int); static void io_ready_exit_drv_finish(void); -static int io_ready_exit_drv_control(ErlDrvData, unsigned int, - char *, int, char **, int); +static ErlDrvSSizeT io_ready_exit_drv_control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, + char **, ErlDrvSizeT); static ErlDrvEntry io_ready_exit_drv_entry = { NULL, /* init */ @@ -56,7 +57,17 @@ static ErlDrvEntry io_ready_exit_drv_entry = { io_ready_exit_drv_control, NULL, /* timeout */ NULL, /* outputv */ - NULL /* ready_async */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + NULL, /* event */ + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, /* ERL_DRV_FLAGs */ + NULL, /* handle2 */ + NULL, /* process_exit */ + NULL /* stop_select */ }; /* ------------------------------------------------------------------------- @@ -83,7 +94,7 @@ io_ready_exit_drv_stop(ErlDrvData drv_data) { #ifdef UNIX if (oeddp->fds[0] >= 0) { driver_select(oeddp->port, - (ErlDrvEvent) oeddp->fds[0], + (ErlDrvEvent) (ErlDrvSInt) oeddp->fds[0], DO_READ|DO_WRITE, 0); close(oeddp->fds[0]); @@ -109,15 +120,15 @@ io_ready_exit_ready_input(ErlDrvData drv_data, ErlDrvEvent event) driver_failure_atom(oeddp->port, "ready_input_driver_failure"); } -static int +static ErlDrvSSizeT io_ready_exit_drv_control(ErlDrvData drv_data, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { char *abuf; char *res_str; - int res_len; + ErlDrvSSizeT res_len; IOReadyExitDrvData *oeddp = (IOReadyExitDrvData *) drv_data; #ifndef UNIX res_str = "nyiftos"; @@ -127,9 +138,9 @@ io_ready_exit_drv_control(ErlDrvData drv_data, } else { res_str = "ok"; - write(oeddp->fds[1], "!", 1); + (void) write(oeddp->fds[1], "!", 1); driver_select(oeddp->port, - (ErlDrvEvent) oeddp->fds[0], + (ErlDrvEvent) (ErlDrvSInt) oeddp->fds[0], DO_READ|DO_WRITE, 1); } diff --git a/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c b/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c index e49de388b4..b2cc1e785a 100644 --- a/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c +++ b/erts/emulator/test/driver_SUITE_data/ioq_exit_drv.c @@ -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 @@ -91,7 +91,8 @@ static ErlDrvData start(ErlDrvPort port, char *command); static void stop(ErlDrvData drv_data); static void ready_input(ErlDrvData drv_data, ErlDrvEvent event); static void ready_output(ErlDrvData drv_data, ErlDrvEvent event); -static int control(ErlDrvData, unsigned int, char *, int, char **, int); +static ErlDrvSSizeT control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); static void timeout(ErlDrvData drv_data); static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data); static void flush(ErlDrvData drv_data); @@ -155,10 +156,10 @@ start(ErlDrvPort port, char *command) return (ErlDrvData) ddp; } -static int control(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen) +static ErlDrvSSizeT control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { IOQExitDrvData *ddp = (IOQExitDrvData *) drv_data; char *res_str = "nyiftos"; @@ -227,7 +228,7 @@ static int control(ErlDrvData drv_data, res_str = "ok"; done: { - int res_len = strlen(res_str); + ErlDrvSSizeT res_len = strlen(res_str); if (res_len > rlen) { char *abuf = driver_alloc(sizeof(char)*res_len); if (!abuf) diff --git a/erts/emulator/test/driver_SUITE_data/many_events_drv.c b/erts/emulator/test/driver_SUITE_data/many_events_drv.c index 7417dbf7f8..a34432a8fe 100644 --- a/erts/emulator/test/driver_SUITE_data/many_events_drv.c +++ b/erts/emulator/test/driver_SUITE_data/many_events_drv.c @@ -3,14 +3,17 @@ #endif #include <stdio.h> +#include <string.h> #include "erl_driver.h" static ErlDrvPort erlang_port; static ErlDrvData many_events_start(ErlDrvPort, char *); -static void from_erlang(ErlDrvData, char*, int); +static void from_erlang(ErlDrvData, char*, ErlDrvSizeT); static void from_port(ErlDrvData drv_data, ErlDrvEvent event); -static int many_events_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags); +static ErlDrvSSizeT many_events_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, + unsigned *ret_flags); static ErlDrvEntry many_events_driver_entry = { NULL, /* Init */ many_events_start, @@ -26,7 +29,15 @@ static ErlDrvEntry many_events_driver_entry = { NULL, NULL, NULL, - many_events_call + many_events_call, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL }; DRIVER_INIT(many_events_drv) @@ -41,7 +52,7 @@ many_events_start(ErlDrvPort port, char *buf) } static void -from_erlang(ErlDrvData data, char *buf, int count) +from_erlang(ErlDrvData data, char *buf, ErlDrvSizeT count) { int i; int num; @@ -87,9 +98,10 @@ static void from_port(ErlDrvData data, ErlDrvEvent ev) return; } -static int -many_events_call(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen, unsigned *ret_flags) +static ErlDrvSSizeT +many_events_call(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, + unsigned *ret_flags) { *rbuf = buf; *ret_flags |= DRIVER_CALL_KEEP_BUFFER; diff --git a/erts/emulator/test/driver_SUITE_data/monitor_drv.c b/erts/emulator/test/driver_SUITE_data/monitor_drv.c index 1da6a56a72..3da067fd09 100644 --- a/erts/emulator/test/driver_SUITE_data/monitor_drv.c +++ b/erts/emulator/test/driver_SUITE_data/monitor_drv.c @@ -21,8 +21,9 @@ #include "erl_driver.h" static ErlDrvData monitor_drv_start(ErlDrvPort, char *); -static int monitor_drv_control(ErlDrvData, unsigned int, - char *, int, char **, int); +static void monitor_drv_stop(ErlDrvData data); +static ErlDrvSSizeT monitor_drv_control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); static void handle_monitor(ErlDrvData drv_data, ErlDrvMonitor *monitor); #define OP_I_AM_IPID 1 @@ -50,7 +51,7 @@ typedef struct { static ErlDrvEntry monitor_drv_entry = { NULL /* init */, monitor_drv_start, - NULL /* stop */, + monitor_drv_stop, NULL /* output */, NULL /* ready_input */, NULL /* ready_output */, @@ -122,16 +123,16 @@ static void handle_monitor(ErlDrvData drv_data, ErlDrvMonitor *monitor) return; } -static int +static ErlDrvSSizeT monitor_drv_control(ErlDrvData drv_data, unsigned int command, - char *ibuf, int ilen, - char **rbuf, int rlen) + char *ibuf, ErlDrvSizeT ilen, + char **rbuf, ErlDrvSizeT rlen) { MyDrvData *data = (MyDrvData *) drv_data; char *answer = NULL; char buff[64]; - int alen; + ErlDrvSSizeT alen; switch (command) { case OP_I_AM_IPID: diff --git a/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c b/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c index 8c0a9aadfd..ff44145ca7 100644 --- a/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c +++ b/erts/emulator/test/driver_SUITE_data/otp_6879_drv.c @@ -20,11 +20,11 @@ #include <string.h> #include "erl_driver.h" -static int call(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen, - unsigned int *flags); +static ErlDrvSSizeT call(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, + unsigned int *flags); static ErlDrvEntry otp_6879_drv_entry = { NULL /* init */, @@ -57,11 +57,11 @@ DRIVER_INIT(otp_6879_drv) } -static int call(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen, - unsigned int *flags) +static ErlDrvSSizeT call(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen, + unsigned int *flags) { /* echo call */ if (len > rlen) diff --git a/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c b/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c index beee1b735f..221fd0ce51 100644 --- a/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c +++ b/erts/emulator/test/driver_SUITE_data/otp_9302_drv.c @@ -28,7 +28,7 @@ static void stop(ErlDrvData drv_data); static ErlDrvData start(ErlDrvPort port, char *command); static void output(ErlDrvData drv_data, - char *buf, int len); + char *buf, ErlDrvSizeT len); static void ready_async(ErlDrvData drv_data, ErlDrvThreadData thread_data); @@ -196,13 +196,13 @@ static void ready_async(ErlDrvData drv_data, } static void output(ErlDrvData drv_data, - char *buf, int len) + char *buf, ErlDrvSizeT len) { Otp9302Data *data = (Otp9302Data *) drv_data; ErlDrvTermData td_port = driver_mk_port(data->port); ErlDrvTermData td_receiver = driver_caller(data->port); ErlDrvTermData td_job = driver_mk_atom("job"); - unsigned int key = (unsigned int) data->port; + unsigned int key = (unsigned int) (ErlDrvSInt) data->port; long id[5]; Otp9302AsyncData *ad[5]; int i; diff --git a/erts/emulator/test/driver_SUITE_data/outputv_drv.c b/erts/emulator/test/driver_SUITE_data/outputv_drv.c index 87f66ae413..3e3d4a3a03 100644 --- a/erts/emulator/test/driver_SUITE_data/outputv_drv.c +++ b/erts/emulator/test/driver_SUITE_data/outputv_drv.c @@ -3,7 +3,9 @@ static ErlDrvPort erlang_port; static ErlDrvData outputv_start(ErlDrvPort, char*); -static void outputv_stop(ErlDrvData), outputv_read(ErlDrvData, char*, int), outputv(ErlDrvData, ErlIOVec*); +static void outputv_stop(ErlDrvData), + outputv_read(ErlDrvData, char*, ErlDrvSizeT), + outputv(ErlDrvData, ErlIOVec*); static ErlDrvEntry outputv_driver_entry = { @@ -19,6 +21,16 @@ static ErlDrvEntry outputv_driver_entry = NULL, NULL, outputv, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -38,7 +50,7 @@ static ErlDrvData outputv_start(ErlDrvPort port, char *buf) return (ErlDrvData)port; } -static void outputv_read(ErlDrvData port, char *buf, int count) +static void outputv_read(ErlDrvData port, char *buf, ErlDrvSizeT count) { erlang_port = (ErlDrvPort)-1; } diff --git a/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c b/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c index 3a5b5af13a..8e203f74ec 100644 --- a/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c +++ b/erts/emulator/test/driver_SUITE_data/peek_non_existing_queue_drv.c @@ -66,7 +66,8 @@ typedef struct { static ErlDrvData start(ErlDrvPort, char *); static void stop(ErlDrvData); -static int control(ErlDrvData, unsigned int, char *, int, char **, int); +static ErlDrvSSizeT control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); static void ready_async(ErlDrvData, ErlDrvThreadData); static void async_test(void *); static void async_wait(void *); @@ -121,10 +122,10 @@ static void stop(ErlDrvData drv_data) driver_free(drv_data); } -static int control(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen) +static ErlDrvSSizeT control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { PeekNonXQDrvData *dp = (PeekNonXQDrvData *) drv_data; unsigned int key = 0; @@ -158,7 +159,7 @@ static int control(ErlDrvData drv_data, } done: { - int res_len = strlen(res_str); + ErlDrvSSizeT res_len = strlen(res_str); if (res_len > rlen) { char *abuf = driver_alloc(sizeof(char)*res_len); if (!abuf) diff --git a/erts/emulator/test/driver_SUITE_data/queue_drv.c b/erts/emulator/test/driver_SUITE_data/queue_drv.c index ded69f89f9..a02b57dc9a 100644 --- a/erts/emulator/test/driver_SUITE_data/queue_drv.c +++ b/erts/emulator/test/driver_SUITE_data/queue_drv.c @@ -1,4 +1,5 @@ #include <stdio.h> +#include <string.h> #include "erl_driver.h" #define put_int32(i, s) {((char*)(s))[0] = (char)((i) >> 24) & 0xff; \ @@ -33,9 +34,10 @@ static ErlDrvPort erlang_port; static unsigned opcode; /* Opcode for next operation. */ static ErlDrvData queue_start(ErlDrvPort, char*); -static void queue_stop(ErlDrvData), queue_read(ErlDrvData, char*, int); +static void queue_stop(ErlDrvData), queue_read(ErlDrvData, char*, ErlDrvSizeT); static void queue_outputv(ErlDrvData, ErlIOVec*); -static int control(ErlDrvData, unsigned int, char*, int, char**, int); +static ErlDrvSSizeT control(ErlDrvData, unsigned int, + char*, ErlDrvSizeT, char**, ErlDrvSizeT); static ErlDrvBinary* read_head(ErlDrvPort, int bytes); static ErlDrvEntry queue_driver_entry = @@ -52,6 +54,16 @@ static ErlDrvEntry queue_driver_entry = control, NULL, queue_outputv, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -73,7 +85,7 @@ static ErlDrvData queue_start(ErlDrvPort port, char *buf) } /* messages from Erlang */ -static void queue_read(ErlDrvData port, char *buf, int len) +static void queue_read(ErlDrvData port, char *buf, ErlDrvSizeT len) { } @@ -82,8 +94,9 @@ static void queue_stop(ErlDrvData port) erlang_port = (ErlDrvPort) -1; } -static int -control(ErlDrvData drv_data, unsigned command, char* buf, int len, char** rbuf, int rlen) +static ErlDrvSSizeT +control(ErlDrvData drv_data, unsigned command, + char* buf, ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rlen) { ErlDrvBinary* b; diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_1_0_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c index 0504778086..c22a415c59 100644 --- a/erts/emulator/test/driver_SUITE_data/sys_info_1_0_drv.c +++ b/erts/emulator/test/driver_SUITE_data/sys_info_base_drv.c @@ -3,34 +3,35 @@ * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' - * + * * $Id$ */ /* * Author: Rickard Green * - * Description: Driver that fakes driver version 1.0 and tests + * Description: Driver that fakes driver version 2.0 and tests * driver_system_info(). * */ #include "sys_info_drv_impl.h" -#define SYS_INFO_DRV_MAJOR_VSN 1 +#define SYS_INFO_DRV_MAJOR_VSN 2 #define SYS_INFO_DRV_MINOR_VSN 0 -#define SYS_INFO_DRV_NAME_STR "sys_info_1_0_drv" -#define SYS_INFO_DRV_NAME sys_info_1_0_drv +#define SYS_INFO_DRV_NAME_STR "sys_info_base_drv" +#define SYS_INFO_DRV_NAME sys_info_base_drv #define SYS_INFO_DRV_LAST_FIELD smp_support +#define ERL_DRV_SYS_INFO_SIZE sizeof(ErlDrvSysInfo) #define SYS_INFO_DRV_RES_FORMAT "ok: " \ "drv_drv_vsn=%d.%d " \ @@ -38,8 +39,9 @@ "erts_vsn=%s " \ "otp_vsn=%s " \ "thread=%s " \ - "smp=%s" - + "smp=%s " \ + "async_thrs=%d " \ + "sched_thrs=%d" static size_t sys_info_drv_max_res_len(ErlDrvSysInfo *sip) @@ -51,6 +53,8 @@ sys_info_drv_max_res_len(ErlDrvSysInfo *sip) slen += strlen(sip->otp_release) + 1; slen += 5; /* threads */ slen += 5; /* smp */ + slen += 20; /* async_thrs */ + slen += 20; /* sched_thrs */ return slen; } @@ -66,7 +70,9 @@ sys_info_drv_sprintf_sys_info(ErlDrvSysInfo *sip, char *str) sip->erts_version, sip->otp_release, sip->thread_support ? "true" : "false", - sip->smp_support ? "true" : "false"); + sip->smp_support ? "true" : "false", + sip->async_threads, + sip->scheduler_threads); } #include "sys_info_drv_impl.c" diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c b/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c index 2d3203ae5d..c6c70a2075 100644 --- a/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c +++ b/erts/emulator/test/driver_SUITE_data/sys_info_drv_impl.c @@ -46,7 +46,8 @@ #endif static ErlDrvData start(ErlDrvPort, char *); -static int control(ErlDrvData, unsigned int, char *, int, char **, int); +static ErlDrvSSizeT control(ErlDrvData, unsigned int, + char *, ErlDrvSizeT, char **, ErlDrvSizeT); static ErlDrvEntry drv_entry = { NULL /* init */, @@ -84,13 +85,13 @@ start(ErlDrvPort port, char *command) return (ErlDrvData) port; } -static int +static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { - int res; + ErlDrvSSizeT res; char *str; size_t slen, slen2; ErlDrvPort port = (ErlDrvPort) drv_data; diff --git a/erts/emulator/test/driver_SUITE_data/sys_info_1_1_drv.c b/erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c index fa21828284..815d96cc97 100644 --- a/erts/emulator/test/driver_SUITE_data/sys_info_1_1_drv.c +++ b/erts/emulator/test/driver_SUITE_data/sys_info_prev_drv.c @@ -3,34 +3,35 @@ * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' - * + * * $Id$ */ /* * Author: Rickard Green * - * Description: Driver that fakes driver version 1.1 and tests + * Description: Driver that fakes driver version 2.0 and tests * driver_system_info(). * */ #include "sys_info_drv_impl.h" -#define SYS_INFO_DRV_MAJOR_VSN 1 -#define SYS_INFO_DRV_MINOR_VSN 1 -#define SYS_INFO_DRV_NAME_STR "sys_info_1_1_drv" -#define SYS_INFO_DRV_NAME sys_info_1_1_drv +#define SYS_INFO_DRV_MAJOR_VSN 2 +#define SYS_INFO_DRV_MINOR_VSN 0 +#define SYS_INFO_DRV_NAME_STR "sys_info_prev_drv" +#define SYS_INFO_DRV_NAME sys_info_prev_drv #define SYS_INFO_DRV_LAST_FIELD scheduler_threads +#define ERL_DRV_SYS_INFO_SIZE sizeof(ErlDrvSysInfo) #define SYS_INFO_DRV_RES_FORMAT "ok: " \ "drv_drv_vsn=%d.%d " \ @@ -42,7 +43,6 @@ "async_thrs=%d " \ "sched_thrs=%d" - static size_t sys_info_drv_max_res_len(ErlDrvSysInfo *sip) { @@ -76,5 +76,3 @@ sys_info_drv_sprintf_sys_info(ErlDrvSysInfo *sip, char *str) } #include "sys_info_drv_impl.c" - - diff --git a/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c b/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c index c7edbba7f6..95a6ae9bdf 100644 --- a/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c +++ b/erts/emulator/test/driver_SUITE_data/thr_alloc_drv.c @@ -21,14 +21,8 @@ #include "erl_driver.h" ErlDrvData start(ErlDrvPort port, char *command); -int control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen); - -static int call(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen, - unsigned int *flags); +ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); static ErlDrvEntry thr_alloc_drv_entry = { NULL /* init */, @@ -76,12 +70,12 @@ ErlDrvData start(ErlDrvPort port, char *command) return (ErlDrvData) port; } -int control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen) +ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { ErlDrvPort port = (ErlDrvPort) drv_data; char *result = "failure"; - int result_len; + ErlDrvSSizeT result_len; if (len <= 20) { int res; ErlDrvTid tid; diff --git a/erts/emulator/test/driver_SUITE_data/thr_free_drv.c b/erts/emulator/test/driver_SUITE_data/thr_free_drv.c index 622a62ebea..439fe6a184 100644 --- a/erts/emulator/test/driver_SUITE_data/thr_free_drv.c +++ b/erts/emulator/test/driver_SUITE_data/thr_free_drv.c @@ -45,8 +45,8 @@ typedef struct { static ErlDrvData start(ErlDrvPort port, char *command); static void stop(ErlDrvData data); -static int control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen); +static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); static ErlDrvEntry thr_free_drv_entry = { NULL /* init */, @@ -175,7 +175,7 @@ fail: driver_free(ttd[t].blocks[b]); } } - + driver_free(td); return ERL_DRV_ERROR_GENERAL; } @@ -194,14 +194,14 @@ static void stop(ErlDrvData drv_data) driver_free(td); } -static int control(ErlDrvData drv_data, unsigned int command, char *buf, - int len, char **rbuf, int rlen) +static ErlDrvSSizeT control(ErlDrvData drv_data, unsigned int command, char *buf, + ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { test_data *td = (test_data *) drv_data; char *result = "failure"; int i, b; int res; - int result_len; + ErlDrvSSizeT result_len; if (td->b == -1) { erl_drv_mutex_lock(td->ttd[0].mtx); diff --git a/erts/emulator/test/driver_SUITE_data/timer_drv.c b/erts/emulator/test/driver_SUITE_data/timer_drv.c index b96a95dd4c..8c3f203a64 100644 --- a/erts/emulator/test/driver_SUITE_data/timer_drv.c +++ b/erts/emulator/test/driver_SUITE_data/timer_drv.c @@ -22,7 +22,9 @@ static ErlDrvPort erlang_port; static ErlDrvData timer_start(ErlDrvPort, char*); -static void timer_stop(ErlDrvData), timer_read(ErlDrvData, char*, int), timer(ErlDrvData); +static void timer_stop(ErlDrvData); +static void timer_read(ErlDrvData, char*, ErlDrvSizeT); +static void timer(ErlDrvData); static ErlDrvEntry timer_driver_entry = { @@ -38,6 +40,16 @@ static ErlDrvEntry timer_driver_entry = NULL, timer, NULL, + NULL, + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, NULL }; @@ -57,8 +69,9 @@ static ErlDrvData timer_start(ErlDrvPort port, char *buf) } /* set the timer, this is monitored from erlang measuring the time */ -static void timer_read(ErlDrvData port, char *buf, int len) +static void timer_read(ErlDrvData p, char *buf, ErlDrvSizeT len) { + ErlDrvPort port = (ErlDrvPort) p; char reply[1]; if (buf[0] == START_TIMER) { diff --git a/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c b/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c index 1e98844838..b4542f3e36 100644 --- a/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c +++ b/erts/emulator/test/erl_drv_thread_SUITE_data/testcase_driver.c @@ -50,13 +50,33 @@ typedef struct { ErlDrvData testcase_drv_start(ErlDrvPort port, char *command); void testcase_drv_stop(ErlDrvData drv_data); -void testcase_drv_run(ErlDrvData drv_data, char *buf, int len); +void testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); static ErlDrvEntry testcase_drv_entry = { NULL, testcase_drv_start, testcase_drv_stop, - testcase_drv_run + testcase_drv_run, + NULL, + NULL, + NULL, + NULL, + NULL, /* handle */ + NULL, /* control */ + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, + }; @@ -92,7 +112,7 @@ testcase_drv_stop(ErlDrvData drv_data) } void -testcase_drv_run(ErlDrvData drv_data, char *buf, int len) +testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data; ErlDrvTermData result_atom; diff --git a/erts/emulator/test/exception_SUITE.erl b/erts/emulator/test/exception_SUITE.erl index 9d6fc9521d..109cec25cb 100644 --- a/erts/emulator/test/exception_SUITE.erl +++ b/erts/emulator/test/exception_SUITE.erl @@ -23,9 +23,10 @@ init_per_group/2,end_per_group/2, badmatch/1, pending_errors/1, nil_arith/1, stacktrace/1, nested_stacktrace/1, raise/1, gunilla/1, per/1, - exception_with_heap_frag/1]). + exception_with_heap_frag/1, line_numbers/1]). -export([bad_guy/2]). +-export([crash/1]). -include_lib("test_server/include/test_server.hrl"). -import(lists, [foreach/2]). @@ -35,7 +36,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [badmatch, pending_errors, nil_arith, stacktrace, nested_stacktrace, raise, gunilla, per, - exception_with_heap_frag]. + exception_with_heap_frag, line_numbers]. groups() -> []. @@ -141,14 +142,20 @@ pending_exit_message(Args, Expected) -> end, process_flag(trap_exit, false). -pending({badarg, [{erlang,Bif,BifArgs},{?MODULE,Func,Arity}|_]}, Func, Args, _Code) - when is_atom(Bif), is_list(BifArgs), length(Args) == Arity -> +pending({badarg,[{erlang,Bif,BifArgs,Loc1}, + {?MODULE,Func,Arity,Loc2}|_]}, + Func, Args, _Code) + when is_atom(Bif), is_list(BifArgs), length(Args) =:= Arity, + is_list(Loc1), is_list(Loc2) -> ok; -pending({undef,[{non_existing_module,foo,[]}|_]}, _, _, _) -> +pending({undef,[{non_existing_module,foo,[],Loc}|_]}, _, _, _) + when is_list(Loc) -> ok; -pending({function_clause,[{?MODULE,Func,Args}|_]}, Func, Args, _Code) -> +pending({function_clause,[{?MODULE,Func,Args,Loc}|_]}, Func, Args, _Code) + when is_list(Loc) -> ok; -pending({Code,[{?MODULE,Func,Arity}|_]}, Func, Args, Code) when length(Args) == Arity -> +pending({Code,[{?MODULE,Func,Arity,Loc}|_]}, Func, Args, Code) + when length(Args) =:= Arity, is_list(Loc) -> ok; pending(Reason, _Function, _Args, _Code) -> test_server:fail({bad_exit_reason,Reason}). @@ -255,24 +262,24 @@ stacktrace(Conf) when is_list(Conf) -> ?line {_,Mref} = spawn_monitor(fun() -> exit({Tag,erlang:get_stacktrace()}) end), ?line {Tag,[]} = receive {'DOWN',Mref,_,_,Info} -> Info end, V = [make_ref()|self()], - ?line {value2,{caught1,badarg,[{erlang,abs,[V]}|_]=St1}} = + ?line {value2,{caught1,badarg,[{erlang,abs,[V],_}|_]=St1}} = stacktrace_1({'abs',V}, error, {value,V}), ?line St1 = erase(stacktrace1), ?line St1 = erase(stacktrace2), ?line St1 = erlang:get_stacktrace(), - ?line {caught2,{error,badarith},[{?MODULE,my_add,2}|_]=St2} = + ?line {caught2,{error,badarith},[{?MODULE,my_add,2,_}|_]=St2} = stacktrace_1({'div',{1,0}}, error, {'add',{0,a}}), - ?line [{?MODULE,my_div,2}|_] = erase(stacktrace1), + ?line [{?MODULE,my_div,2,_}|_] = erase(stacktrace1), ?line St2 = erase(stacktrace2), ?line St2 = erlang:get_stacktrace(), - ?line {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3}|_]=St3} = + ?line {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3,_}|_]=St3} = stacktrace_1({value,V}, error, {value,V}), ?line St3 = erase(stacktrace1), ?line St3 = erase(stacktrace2), ?line St3 = erlang:get_stacktrace(), - ?line {caught2,{throw,V},[{?MODULE,foo,1}|_]=St4} = + ?line {caught2,{throw,V},[{?MODULE,foo,1,_}|_]=St4} = stacktrace_1({value,V}, error, {throw,V}), - ?line [{?MODULE,stacktrace_1,3}|_] = erase(stacktrace1), + ?line [{?MODULE,stacktrace_1,3,_}|_] = erase(stacktrace1), ?line St4 = erase(stacktrace2), ?line St4 = erlang:get_stacktrace(), @@ -280,8 +287,8 @@ stacktrace(Conf) when is_list(Conf) -> ?line stacktrace_2() catch error:{badmatch,_} -> - [{?MODULE,stacktrace_2,0}, - {?MODULE,stacktrace,1}|_] = + [{?MODULE,stacktrace_2,0,_}, + {?MODULE,stacktrace,1,_}|_] = erlang:get_stacktrace(), ok end. @@ -315,15 +322,15 @@ nested_stacktrace(Conf) when is_list(Conf) -> nested_stacktrace_1({{value,{V,x1}},void,{V,x1}}, {void,void,void}), ?line {caught1, - [{?MODULE,my_add,2}|_], + [{?MODULE,my_add,2,_}|_], value2, - [{?MODULE,my_add,2}|_]} = + [{?MODULE,my_add,2,_}|_]} = nested_stacktrace_1({{'add',{V,x1}},error,badarith}, {{value,{V,x2}},void,{V,x2}}), ?line {caught1, - [{?MODULE,my_add,2}|_], - {caught2,[{erlang,abs,[V]}|_]}, - [{erlang,abs,[V]}|_]} = + [{?MODULE,my_add,2,_}|_], + {caught2,[{erlang,abs,[V],_}|_]}, + [{erlang,abs,[V],_}|_]} = nested_stacktrace_1({{'add',{V,x1}},error,badarith}, {{'abs',V},error,badarg}), ok. @@ -362,14 +369,14 @@ raise(Conf) when is_list(Conf) -> end, ?line A = erlang:get_stacktrace(), ?line A = get(raise), - ?line [{?MODULE,my_div,2}|_] = A, + ?line [{?MODULE,my_div,2,_}|_] = A, %% N = 8, % Must be even ?line N = erlang:system_flag(backtrace_depth, N), + ?line B = odd_even(N, []), ?line try even(N) catch error:function_clause -> ok end, - ?line B = odd_even(N, []), ?line B = erlang:get_stacktrace(), %% ?line C0 = odd_even(N+1, []), @@ -387,19 +394,12 @@ raise(Conf) when is_list(Conf) -> odd_even(N, R) when is_integer(N), N > 1 -> odd_even(N-1, [if (N rem 2) == 0 -> - {?MODULE,even,1}; + {?MODULE,even,1,[{file,"odd_even.erl"},{line,3}]}; true -> - {?MODULE,odd,1} + {?MODULE,odd,1,[{file,"odd_even.erl"},{line,6}]} end|R]); odd_even(1, R) -> - [{?MODULE,odd,[1]}|R]. - -even(N) when is_integer(N), N > 1, (N rem 2) == 0 -> - odd(N-1)++[N]. - -odd(N) when is_integer(N), N > 1, (N rem 2) == 1 -> - even(N-1)++[N]. - + [{?MODULE,odd,[1],[{file,"odd_even.erl"},{line,5}]}|R]. foo({value,Value}) -> Value; foo({'div',{A,B}}) -> @@ -526,4 +526,186 @@ do_exception_with_heap_frag(Bin, [Sz|Sizes]) -> do_exception_with_heap_frag(Bin, Sizes); do_exception_with_heap_frag(_, []) -> ok. +line_numbers(Config) when is_list(Config) -> + {'EXIT',{{case_clause,bad_tag}, + [{?MODULE,line1,2, + [{file,"fake_file.erl"},{line,3}]}, + {?MODULE,line_numbers,1,_}|_]}} = + (catch line1(bad_tag, 0)), + {'EXIT',{badarith, + [{?MODULE,line1,2, + [{file,"fake_file.erl"},{line,5}]}, + {?MODULE,line_numbers,1,_}|_]}} = + (catch line1(a, not_an_integer)), + {'EXIT',{{badmatch,{ok,1}}, + [{?MODULE,line1,2, + [{file,"fake_file.erl"},{line,7}]}, + {?MODULE,line_numbers,1,_}|_]}} = + (catch line1(a, 0)), + {'EXIT',{crash, + [{?MODULE,crash,1, + [{file,"fake_file.erl"},{line,14}]}, + {?MODULE,line_numbers,1,_}|_]}} = + (catch line1(a, 41)), + + ModFile = ?MODULE_STRING++".erl", + [{?MODULE,maybe_crash,1,[{file,"call.erl"},{line,28}]}, + {?MODULE,call1,0,[{file,"call.erl"},{line,14}]}, + {?MODULE,close_calls,1,[{file,"call.erl"},{line,5}]}, + {?MODULE,line_numbers,1,[{file,ModFile},{line,_}]}|_] = + close_calls(call1), + [{?MODULE,maybe_crash,1,[{file,"call.erl"},{line,28}]}, + {?MODULE,call2,0,[{file,"call.erl"},{line,18}]}, + {?MODULE,close_calls,1,[{file,"call.erl"},{line,6}]}, + {?MODULE,line_numbers,1,[{file,ModFile},{line,_}]}|_] = + close_calls(call2), + [{?MODULE,maybe_crash,1,[{file,"call.erl"},{line,28}]}, + {?MODULE,call3,0,[{file,"call.erl"},{line,22}]}, + {?MODULE,close_calls,1,[{file,"call.erl"},{line,7}]}, + {?MODULE,line_numbers,1,[{file,ModFile},{line,_}]}|_] = + close_calls(call3), + no_crash = close_calls(other), + + <<0,0>> = build_binary1(16), + {'EXIT',{badarg, + [{?MODULE,build_binary1,1, + [{file,"bit_syntax.erl"},{line,72503}]}, + {?MODULE,line_numbers,1, + [{file,ModFile},{line,_}]}|_]}} = + (catch build_binary1(bad_size)), + + <<7,1,2,3>> = build_binary2(8, <<1,2,3>>), + {'EXIT',{badarg, + [{?MODULE,build_binary2,2, + [{file,"bit_syntax.erl"},{line,72507}]}, + {?MODULE,line_numbers,1, + [{file,ModFile},{line,_}]}|_]}} = + (catch build_binary2(bad_size, <<>>)), + {'EXIT',{badarg, + [{erlang,bit_size,[bad_binary],[]}, + {?MODULE,build_binary2,2, + [{file,"bit_syntax.erl"},{line,72507}]}, + {?MODULE,line_numbers,1, + [{file,ModFile},{line,_}]}|_]}} = + (catch build_binary2(8, bad_binary)), + + {'EXIT',{function_clause, + [{?MODULE,do_call_abs,[y,y], + [{file,"gc_bif.erl"},{line,18}]}, + {?MODULE,line_numbers,1,_}|_]}} = + (catch do_call_abs(y, y)), + {'EXIT',{badarg, + [{erlang,abs,[[]],[]}, + {?MODULE,do_call_abs,2, + [{file,"gc_bif.erl"},{line,19}]}, + {?MODULE,line_numbers,1,_}|_]}} = + (catch do_call_abs(x, [])), + + {'EXIT',{{badmatch,"42"}, + [{MODULE,applied_bif_1,1,[{file,"applied_bif.erl"},{line,5}]}, + {?MODULE,line_numbers,1,_}|_]}} = + (catch applied_bif_1(42)), + + {'EXIT',{{badmatch,{current_location, + {?MODULE,applied_bif_2,0, + [{file,"applied_bif.erl"},{line,9}]}}}, + [{MODULE,applied_bif_2,0,[{file,"applied_bif.erl"},{line,10}]}, + {?MODULE,line_numbers,1,_}|_]}} = + (catch applied_bif_2()), + + ok. + id(I) -> I. + +-file("odd_even.erl", 1). %Line 1 +even(N) when is_integer(N), N > 1, (N rem 2) == 0 -> + odd(N-1)++[N]. %Line 3 + +odd(N) when is_integer(N), N > 1, (N rem 2) == 1 -> + even(N-1)++[N]. %Line 6 + +%% +%% If the compiler removes redundant line instructions (any +%% line instruction with the same location as the previous), +%% and the loader also removes line instructions before +%% tail-recursive calls to external functions, then the +%% badmatch exception in line 7 below will be reported as +%% occurring in line 6. +%% +%% That means that any removal of redundant line instructions +%% must all be done in the compiler OR in the loader. +%% +-file("fake_file.erl", 1). %Line 1 +line1(Tag, X) -> %Line 2 + case Tag of %Line 3 + a -> + Y = X + 1, %Line 5 + Res = id({ok,Y}), %Line 6 + ?MODULE:crash({ok,42} = Res); %Line 7 + b -> + x = id(x), %Line 9 + ok %Line 10 + end. %Line 11 + +crash(_) -> %Line 13 + erlang:error(crash). %Line 14 + +-file("call.erl", 1). %Line 1 +close_calls(Where) -> %Line 2 + put(where_to_crash, Where), %Line 3 + try + call1(), %Line 5 + call2(), %Line 6 + call3(), %Line 7 + no_crash %Line 8 + catch error:crash -> + erlang:get_stacktrace() %Line 10 + end. %Line 11 + +call1() -> %Line 13 + maybe_crash(call1), %Line 14 + ok. %Line 15 + +call2() -> %Line 17 + maybe_crash(call2), %Line 18 + ok. %Line 19 + +call3() -> %Line 21 + maybe_crash(call3), %Line 22 + ok. %Line 23 + +maybe_crash(Name) -> %Line 25 + case get(where_to_crash) of %Line 26 + Name -> + erlang:error(crash); %Line 28 + _ -> + ok %Line 30 + end. + +-file("bit_syntax.erl", 72500). %Line 72500 +build_binary1(Size) -> %Line 72501 + id(42), %Line 72502 + <<0:Size>>. %Line 72503 + +build_binary2(Size, Bin) -> %Line 72505 + id(0), %Line 72506 + <<7:Size,Bin/binary>>. %Line 72507 + +-file("gc_bif.erl", 17). +do_call_abs(x, Arg) -> %Line 18 + abs(Arg). %Line 19 + +%% Make sure a BIF that is applied does not leave the p->cp +%% set (and thus generating an extra entry on the stack). + +-file("applied_bif.erl", 1). +%% Explicit apply. +applied_bif_1(I) -> %Line 3 + L = apply(erlang, integer_to_list, [I]), %Line 4 + fail = L, %Line 5 + ok. %Line 6 +%% Implicit apply. +applied_bif_2() -> %Line 8 + R = process_info(self(), current_location), %Line 9 + fail = R, %Line 10 + ok. %Line 11 diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl index 736510339f..8e6923ce9f 100644 --- a/erts/emulator/test/float_SUITE.erl +++ b/erts/emulator/test/float_SUITE.erl @@ -25,8 +25,9 @@ init_per_group/2,end_per_group/2, init_per_testcase/2,end_per_testcase/2, fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1, - bad_float_unpack/1]). + bad_float_unpack/1,cmp_zero/1, cmp_integer/1, cmp_bignum/1]). -export([otp_7178/1]). +-export([hidden_inf/1]). init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> @@ -41,10 +42,12 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [fpe, fp_drv, fp_drv_thread, otp_7178, denormalized, - match, bad_float_unpack]. + match, bad_float_unpack, {group, comparison} + ,hidden_inf + ]. groups() -> - []. + [{comparison, [parallel], [cmp_zero, cmp_integer, cmp_bignum]}]. init_per_suite(Config) -> Config. @@ -187,6 +190,101 @@ bad_float_unpack(Config) when is_list(Config) -> bad_float_unpack_match(<<F:64/float>>) -> F; bad_float_unpack_match(<<I:64/integer-signed>>) -> I. +cmp_zero(_Config) -> + cmp(0.5e-323,0). + +cmp_integer(_Config) -> + Axis = (1 bsl 53)-2.0, %% The point where floating points become unprecise + span_cmp(Axis,2,200), + cmp(Axis*Axis,round(Axis)). + +cmp_bignum(_Config) -> + span_cmp((1 bsl 58) - 1.0),%% Smallest bignum float + + %% Test when the big num goes from I to I+1 in size + [span_cmp((1 bsl (32*I)) - 1.0) || I <- lists:seq(2,30)], + + %% Test bignum greater then largest float + cmp((1 bsl (64*16)) - 1, (1 bsl (64*15)) * 1.0), + %% Test when num is much larger then float + [cmp((1 bsl (32*I)) - 1, (1 bsl (32*(I-2))) * 1.0) || I <- lists:seq(3,30)], + %% Test when float is much larger than num + [cmp((1 bsl (64*15)) * 1.0, (1 bsl (32*(I)))) || I <- lists:seq(1,29)], + + %% Test that all int == float works as they should + [true = 1 bsl N == (1 bsl N)*1.0 || N <- lists:seq(0, 1023)], + [true = (1 bsl N)*-1 == (1 bsl N)*-1.0 || N <- lists:seq(0, 1023)]. + +span_cmp(Axis) -> + span_cmp(Axis, 25). +span_cmp(Axis, Length) -> + span_cmp(Axis, round(Axis) bsr 52, Length). +span_cmp(Axis, Incr, Length) -> + [span_cmp(Axis, Incr, Length, 1 bsl (1 bsl I)) || I <- lists:seq(0,6)]. +%% This function creates tests around number axis. Both <, > and == is tested +%% for both negative and positive numbers. +%% +%% Axis: The number around which to do the tests eg. (1 bsl 58) - 1.0 +%% Incr: How much to increment the test numbers inbetween each test. +%% Length: Length/2 is the number of Incr away from Axis to test on the +%% negative and positive plane. +%% Diff: How much the float and int should differ when comparing +span_cmp(Axis, Incr, Length, Diff) -> + [begin + cmp(round(Axis*-1.0)+Diff+I*Incr,Axis*-1.0+I*Incr), + cmp(Axis*-1.0+I*Incr,round(Axis*-1.0)-Diff+I*Incr) + end || I <- lists:seq((Length div 2)*-1,(Length div 2))], + [begin + cmp(round(Axis)+Diff+I*Incr,Axis+I*Incr), + cmp(Axis+I*Incr,round(Axis)-Diff+I*Incr) + end || I <- lists:seq((Length div 2)*-1,(Length div 2))]. + +cmp(Big,Small) when is_float(Big) -> + BigGtSmall = lists:flatten( + io_lib:format("~f > ~p",[Big,Small])), + BigLtSmall = lists:flatten( + io_lib:format("~f < ~p",[Big,Small])), + BigEqSmall = lists:flatten( + io_lib:format("~f == ~p",[Big,Small])), + SmallGtBig = lists:flatten( + io_lib:format("~p > ~f",[Small,Big])), + SmallLtBig = lists:flatten( + io_lib:format("~p < ~f",[Small,Big])), + SmallEqBig = lists:flatten( + io_lib:format("~p == ~f",[Small,Big])), + cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig, + SmallEqBig,BigEqSmall); +cmp(Big,Small) when is_float(Small) -> + BigGtSmall = lists:flatten( + io_lib:format("~p > ~f",[Big,Small])), + BigLtSmall = lists:flatten( + io_lib:format("~p < ~f",[Big,Small])), + BigEqSmall = lists:flatten( + io_lib:format("~p == ~f",[Big,Small])), + SmallGtBig = lists:flatten( + io_lib:format("~f > ~p",[Small,Big])), + SmallLtBig = lists:flatten( + io_lib:format("~f < ~p",[Small,Big])), + SmallEqBig = lists:flatten( + io_lib:format("~f == ~p",[Small,Big])), + cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig, + SmallEqBig,BigEqSmall). + +cmp(Big,Small,BigGtSmall,BigLtSmall,SmallGtBig,SmallLtBig, + SmallEqBig,BigEqSmall) -> + {_,_,_,true} = {Big,Small,BigGtSmall, + Big > Small}, + {_,_,_,false} = {Big,Small,BigLtSmall, + Big < Small}, + {_,_,_,false} = {Big,Small,SmallGtBig, + Small > Big}, + {_,_,_,true} = {Big,Small,SmallLtBig, + Small < Big}, + {_,_,_,false} = {Big,Small,SmallEqBig, + Small == Big}, + {_,_,_,false} = {Big,Small,BigEqSmall, + Big == Small}. + id(I) -> I. start_node(Config) when is_list(Config) -> @@ -205,3 +303,25 @@ start_node(Config) when is_list(Config) -> stop_node(Node) -> ?t:stop_node(Node). + + +%% Test that operations that might hide infinite intermediate results +%% do not supress the badarith. +hidden_inf(Config) when is_list(Config) -> + ZeroP = 0.0, + ZeroN = id(ZeroP) * (-1), + [hidden_inf_1(A, B, Z, 9.23e307) + || A <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN], + B <- [1.0, -1.0, 3.1415, -0.00001000131, 3.57e257, ZeroP, ZeroN], + Z <- [ZeroP, ZeroN]], + ok. + +hidden_inf_1(A, B, Zero, Huge) -> + {'EXIT',{badarith,_}} = (catch (B / (A / Zero))), + {'EXIT',{badarith,_}} = (catch (B * (A / Zero))), + {'EXIT',{badarith,_}} = (catch (B / (Huge * Huge))), + {'EXIT',{badarith,_}} = (catch (B * (Huge * Huge))), + {'EXIT',{badarith,_}} = (catch (B / (Huge + Huge))), + {'EXIT',{badarith,_}} = (catch (B * (Huge + Huge))), + {'EXIT',{badarith,_}} = (catch (B / (-Huge - Huge))), + {'EXIT',{badarith,_}} = (catch (B * (-Huge - Huge))). diff --git a/erts/emulator/test/float_SUITE_data/fp_drv.c b/erts/emulator/test/float_SUITE_data/fp_drv.c index eb453f6cd6..b80385c3f9 100644 --- a/erts/emulator/test/float_SUITE_data/fp_drv.c +++ b/erts/emulator/test/float_SUITE_data/fp_drv.c @@ -22,6 +22,7 @@ # define PRINTF(X) #endif +#include <string.h> #include <math.h> #ifdef __WIN32__ #include <float.h> @@ -37,7 +38,8 @@ int _finite(double x); #define ERTS_FP_CONTROL_TEST 0 #define ERTS_FP_THREAD_TEST 1 -static int control(ErlDrvData, unsigned int, char *, int, char **, int); +static ErlDrvSSizeT control(ErlDrvData, unsigned int, char *, + ErlDrvSizeT, char **, ErlDrvSizeT); static ErlDrvEntry fp_drv_entry = { NULL /* init */, @@ -97,10 +99,10 @@ do_test(void *unused) return "ok"; } -static int control(ErlDrvData drv_data, - unsigned int command, - char *buf, int len, - char **rbuf, int rlen) +static ErlDrvSSizeT control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { char *res_str; PRINTF(("control(%p, %d, ...) called\r\n", drv_data, command)); diff --git a/erts/emulator/test/fun_r12_SUITE.erl b/erts/emulator/test/fun_r13_SUITE.erl index 3b1dfc9825..76ddf9fec9 100644 --- a/erts/emulator/test/fun_r12_SUITE.erl +++ b/erts/emulator/test/fun_r13_SUITE.erl @@ -17,10 +17,10 @@ %% %CopyrightEnd% %% --module(fun_r12_SUITE). --compile(r12). +-module(fun_r13_SUITE). +-compile(r13). --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, +-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2,end_per_testcase/2,dist_old_release/1]). @@ -29,10 +29,10 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. -all() -> +all() -> [dist_old_release]. -groups() -> +groups() -> []. init_per_suite(Config) -> diff --git a/erts/emulator/test/guard_SUITE.erl b/erts/emulator/test/guard_SUITE.erl index f41324c2cc..a5df9b59a0 100644 --- a/erts/emulator/test/guard_SUITE.erl +++ b/erts/emulator/test/guard_SUITE.erl @@ -421,7 +421,7 @@ try_gbif(Id, X, Y) -> try_fail_gbif(Id, X, Y) -> case catch guard_bif(Id, X, Y) of - {'EXIT', {function_clause,[{?MODULE,guard_bif,[Id,X,Y]}|_]}} -> + {'EXIT',{function_clause,[{?MODULE,guard_bif,[Id,X,Y],_}|_]}} -> io:format("guard_bif(~p, ~p, ~p) -- ok", [Id,X,Y]); Other -> ?line ok = io:format("guard_bif(~p, ~p, ~p) -- bad result: ~p\n", @@ -493,9 +493,9 @@ type_tests(Test, [Type|T], Allowed) -> end; false -> case catch type_test(Test, Value) of - {'EXIT', {function_clause, {?MODULE,type_test,[Test,Value]}}} -> - ok; - {'EXIT', {function_clause,[{?MODULE,type_test,[Test,Value]}|_]}} -> + {'EXIT',{function_clause, + [{?MODULE,type_test,[Test,Value],Loc}|_]}} + when is_list(Loc) -> ok; {'EXIT',Other} -> ?line test_server:fail({unexpected_error_reason,Other}); diff --git a/erts/emulator/test/mtx_SUITE.erl b/erts/emulator/test/mtx_SUITE.erl index 879d2f61dd..024c3456a8 100644 --- a/erts/emulator/test/mtx_SUITE.erl +++ b/erts/emulator/test/mtx_SUITE.erl @@ -122,7 +122,7 @@ long_rwlock(Config) when is_list(Config) -> %% A very short run time is expected, since %% threads in the test mostly wait ?t:format("RunTime=~p~n", [RunTime]), - ?line true = RunTime < 100, + ?line true = RunTime < 400, ?line RunTimeStr = "Run-time during test was "++integer_to_list(RunTime)++" ms.", case LLRes of ok -> @@ -281,7 +281,7 @@ hammer_sched_rwlock_test(FreqRead, LockCheck, Blocking, WaitLocked, WaitUnlocked _ -> {_, RunTime} = statistics(runtime), ?t:format("RunTime=~p~n", [RunTime]), - ?line true = RunTime < 500, + ?line true = RunTime < 700, {comment, "Run-time during test was " ++ integer_to_list(RunTime) diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index f6344791f1..370363bf9e 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -35,7 +35,9 @@ resource_takeover/1, threading/1, send/1, send2/1, send3/1, send_threaded/1, neg/1, is_checks/1, - get_length/1, make_atom/1, make_string/1]). + get_length/1, make_atom/1, make_string/1, reverse_list_test/1, + otp_9668/1 + ]). -export([many_args_100/100]). @@ -60,7 +62,9 @@ all() -> iolist_as_binary, resource, resource_binary, resource_takeover, threading, send, send2, send3, send_threaded, neg, is_checks, get_length, make_atom, - make_string]. + make_string,reverse_list_test, + otp_9668 + ]. groups() -> []. @@ -1165,7 +1169,28 @@ is_checks(Config) when is_list(Config) -> ?line ensure_lib_loaded(Config, 1), ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end, self(), hd(erlang:ports()), [], [1,9,9,8], - {hejsan, "hejsan", [$h,"ejs",<<"an">>]}), + {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 12), + ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end, + self(), hd(erlang:ports()), [], [1,9,9,8], + {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -12), + ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end, + self(), hd(erlang:ports()), [], [1,9,9,8], + {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 18446744073709551617), + ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end, + self(), hd(erlang:ports()), [], [1,9,9,8], + {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -18446744073709551617), + ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end, + self(), hd(erlang:ports()), [], [1,9,9,8], + {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 99.146), + ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end, + self(), hd(erlang:ports()), [], [1,9,9,8], + {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -99.146), + ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end, + self(), hd(erlang:ports()), [], [1,9,9,8], + {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, 18446744073709551616.2e2), + ?line ok = check_is(hejsan, <<19,98>>, make_ref(), ok, fun() -> ok end, + self(), hd(erlang:ports()), [], [1,9,9,8], + {hejsan, "hejsan", [$h,"ejs",<<"an">>]}, -18446744073709551616.2e2), try ?line error = check_is_exception(), ?line throw(expected_badarg) @@ -1208,6 +1233,27 @@ make_string(Config) when is_list(Config) -> AStringWithAccents = [$E,$r,$l,$a,$n,$g,$ ,16#e4,$r,$ ,$e,$t,$t,$ ,$g,$e,$n,$e,$r,$e,$l,$l,$t,$ ,$p,$r,$o,$g,$r,$a,$m,$s,$p,$r,16#e5,$k], ?line Strings = {A0String,A0String,A0String,A0String0, AStringWithAccents}. +reverse_list_test(Config) -> + ?line ensure_lib_loaded(Config, 1), + List = lists:seq(1,100), + RevList = lists:reverse(List), + ?line RevList = reverse_list(List), + ?line badarg = reverse_list(foo). + +otp_9668(doc) -> ["Memory leak of tmp-buffer when inspecting iolist or unaligned binary in unbound environment"]; +otp_9668(Config) -> + ensure_lib_loaded(Config, 1), + TmpMem = tmpmem(), + IOList = ["This",' ',<<"is">>,' ',[<<"an iolist">>,'.']], + otp_9668_nif(IOList), + + <<_:5/bitstring,UnalignedBin:10/binary,_/bitstring>> = <<"Abuse me as unaligned">>, + otp_9668_nif(UnalignedBin), + + ?line verify_tmpmem(TmpMem), + ok. + + tmpmem() -> case erlang:system_info({allocator,temp_alloc}) of false -> undefined; @@ -1296,7 +1342,7 @@ get_resource(_,_) -> ?nif_stub. release_resource(_) -> ?nif_stub. last_resource_dtor_call() -> ?nif_stub. make_new_resource(_,_) -> ?nif_stub. -check_is(_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. +check_is(_,_,_,_,_,_,_,_,_,_,_) -> ?nif_stub. check_is_exception() -> ?nif_stub. length_test(_,_,_,_,_) -> ?nif_stub. make_atoms() -> ?nif_stub. @@ -1314,8 +1360,10 @@ send_blob_thread(_,_,_) -> ?nif_stub. join_send_thread(_) -> ?nif_stub. copy_blob(_) -> ?nif_stub. send_term(_,_) -> ?nif_stub. +reverse_list(_) -> ?nif_stub. echo_int(_) -> ?nif_stub. type_sizes() -> ?nif_stub. +otp_9668_nif(_) -> ?nif_stub. nif_stub_error(Line) -> exit({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 92f1bab8dd..03092fef5e 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -345,8 +345,13 @@ static int test_double(ErlNifEnv* env, double d1) #define TAG_BITS 4 #define SMALL_BITS (sizeof(void*)*8 - TAG_BITS) +#ifdef _WIN64 +#define MAX_SMALL ((1LL << (SMALL_BITS-1))-1) +#define MIN_SMALL (-(1LL << (SMALL_BITS-1))) +#else #define MAX_SMALL ((1L << (SMALL_BITS-1))-1) #define MIN_SMALL (-(1L << (SMALL_BITS-1))) +#endif static ERL_NIF_TERM type_test(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { @@ -832,6 +837,7 @@ static ERL_NIF_TERM release_resource(ErlNifEnv* env, int argc, const ERL_NIF_TER * argv[7] an empty list * argv[8] a non-empty list * argv[9] a tuple + * argv[10] a number (small, big integer or float) */ static ERL_NIF_TERM check_is(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { @@ -848,6 +854,7 @@ static ERL_NIF_TERM check_is(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] if (!enif_is_list(env, argv[7])) return enif_make_badarg(env); if (!enif_is_list(env, argv[8])) return enif_make_badarg(env); if (!enif_is_tuple(env, argv[9])) return enif_make_badarg(env); + if (!enif_is_number(env, argv[10])) return enif_make_badarg(env); return ok_atom; } @@ -1421,6 +1428,34 @@ static ERL_NIF_TERM send_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ return enif_make_int(env, ret); } +static ERL_NIF_TERM reverse_list(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { + ERL_NIF_TERM rev_list; + + if(!enif_make_reverse_list(env, argv[0], &rev_list)) + return enif_make_atom(env, "badarg"); + return rev_list; +} + +static ERL_NIF_TERM otp_9668_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + /* Inspect in process independent env */ + ErlNifEnv* myenv = enif_alloc_env(); + ERL_NIF_TERM mycopy = enif_make_copy(myenv, argv[0]); + ErlNifBinary obin, cbin; + + if ((enif_inspect_binary(env, argv[0], &obin) + && enif_inspect_binary(myenv, mycopy, &cbin)) + || + (enif_inspect_iolist_as_binary(env, argv[0], &obin) + && enif_inspect_iolist_as_binary(myenv, mycopy, &cbin))) + { + assert(obin.size == cbin.size); + assert(memcmp(obin.data, cbin.data, obin.size) == 0); + } + enif_free_env(myenv); + return atom_ok; +} + static ErlNifFunc nif_funcs[] = { {"lib_version", 0, lib_version}, @@ -1447,7 +1482,7 @@ static ErlNifFunc nif_funcs[] = {"release_resource", 1, release_resource}, {"last_resource_dtor_call", 0, last_resource_dtor_call}, {"make_new_resource", 2, make_new_resource}, - {"check_is", 10, check_is}, + {"check_is", 11, check_is}, {"check_is_exception", 0, check_is_exception}, {"length_test", 5, length_test}, {"make_atoms", 0, make_atoms}, @@ -1466,8 +1501,10 @@ static ErlNifFunc nif_funcs[] = {"join_send_thread", 1, join_send_thread}, {"copy_blob", 1, copy_blob}, {"send_term", 2, send_term}, + {"reverse_list",1, reverse_list}, {"echo_int", 1, echo_int}, - {"type_sizes", 0, type_sizes} + {"type_sizes", 0, type_sizes}, + {"otp_9668_nif", 1, otp_9668_nif} }; ERL_NIF_INIT(nif_SUITE,nif_funcs,load,reload,upgrade,unload) diff --git a/erts/emulator/test/port_SUITE_data/echo_drv.c b/erts/emulator/test/port_SUITE_data/echo_drv.c index 25eda116fe..1d39c6a00c 100644 --- a/erts/emulator/test/port_SUITE_data/echo_drv.c +++ b/erts/emulator/test/port_SUITE_data/echo_drv.c @@ -1,4 +1,5 @@ #include <stdio.h> +#include <string.h> #include "erl_driver.h" @@ -17,11 +18,9 @@ typedef struct _erl_drv_data EchoDrvData; static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command); static void echo_drv_stop(EchoDrvData *data_p); -static void echo_drv_output(EchoDrvData *data_p, char *buf, int len); +static void echo_drv_output(ErlDrvData drv_data, char *buf, + ErlDrvSizeT len); static void echo_drv_finish(void); -static int echo_drv_control(EchoDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen); static ErlDrvEntry echo_drv_entry = { NULL, /* init */ @@ -33,10 +32,20 @@ static ErlDrvEntry echo_drv_entry = { "echo_drv", echo_drv_finish, NULL, /* handle */ - echo_drv_control, + NULL, /* control */ NULL, /* timeout */ NULL, /* outputv */ - NULL /* ready_async */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; @@ -68,7 +77,8 @@ static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command) { static void echo_drv_stop(EchoDrvData *data_p) { } -static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) { +static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { + EchoDrvData *data_p = (EchoDrvData *) drv_data; void *void_ptr; ErlDrvPort port = void_ptr = data_p; @@ -77,9 +87,3 @@ static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) { static void echo_drv_finish() { } - -static int echo_drv_control(EchoDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) { - return 0; -} diff --git a/erts/emulator/test/port_SUITE_data/exit_drv.c b/erts/emulator/test/port_SUITE_data/exit_drv.c index 60f1b321bd..5f366b3545 100644 --- a/erts/emulator/test/port_SUITE_data/exit_drv.c +++ b/erts/emulator/test/port_SUITE_data/exit_drv.c @@ -5,11 +5,9 @@ typedef struct _erl_drv_data ExitDrvData; static ExitDrvData *exit_drv_start(ErlDrvPort port, char *command); static void exit_drv_stop(ExitDrvData *data_p); -static void exit_drv_output(ExitDrvData *data_p, char *buf, int len); +static void exit_drv_output(ExitDrvData *data_p, char *buf, + ErlDrvSizeT len); static void exit_drv_finish(void); -static int exit_drv_control(ExitDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen); static ErlDrvEntry exit_drv_entry = { NULL, /* init */ @@ -21,10 +19,20 @@ static ErlDrvEntry exit_drv_entry = { "exit_drv", exit_drv_finish, NULL, /* handle */ - exit_drv_control, + NULL, /* control */ NULL, /* timeout */ NULL, /* outputv */ - NULL /* ready_async */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; DRIVER_INIT(exit_drv) @@ -45,7 +53,7 @@ exit_drv_stop(ExitDrvData *datap) } static void -exit_drv_output(ExitDrvData *datap, char *buf, int len) +exit_drv_output(ExitDrvData *datap, char *buf, ErlDrvSizeT len) { driver_exit((ErlDrvPort) datap, 0); } @@ -55,14 +63,3 @@ exit_drv_finish(void) { } - -static int -exit_drv_control(ExitDrvData *datap, - unsigned int command, - char *buf, - int len, - char **rbuf, - int rlen) -{ - return 0; -} diff --git a/erts/emulator/test/port_SUITE_data/failure_drv.c b/erts/emulator/test/port_SUITE_data/failure_drv.c index 34d48e00f8..5826e6d5a9 100644 --- a/erts/emulator/test/port_SUITE_data/failure_drv.c +++ b/erts/emulator/test/port_SUITE_data/failure_drv.c @@ -5,10 +5,8 @@ typedef struct _erl_drv_data FailureDrvData; static FailureDrvData *failure_drv_start(ErlDrvPort, char *); static void failure_drv_stop(FailureDrvData *); -static void failure_drv_output(FailureDrvData *, char *, int); +static void failure_drv_output(ErlDrvData, char *, ErlDrvSizeT); static void failure_drv_finish(void); -static int failure_drv_control(FailureDrvData *, unsigned int, - char *, int, char **, int); static ErlDrvEntry failure_drv_entry = { NULL, /* init */ @@ -18,12 +16,22 @@ static ErlDrvEntry failure_drv_entry = { NULL, /* ready_input */ NULL, /* ready_output */ "failure_drv", - failure_drv_finish, + NULL, /* finish */ NULL, /* handle */ - failure_drv_control, + NULL, /* control */ NULL, /* timeout */ NULL, /* outputv */ - NULL /* ready_async */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; @@ -46,7 +54,8 @@ static FailureDrvData *failure_drv_start(ErlDrvPort port, char *command) { static void failure_drv_stop(FailureDrvData *data_p) { } -static void failure_drv_output(FailureDrvData *data_p, char *buf, int len) { +static void failure_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { + FailureDrvData *data_p = (FailureDrvData *) drv_data; void *void_ptr; ErlDrvPort port = void_ptr = data_p; @@ -55,9 +64,3 @@ static void failure_drv_output(FailureDrvData *data_p, char *buf, int len) { static void failure_drv_finish() { } - -static int failure_drv_control(FailureDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) { - return 0; -} diff --git a/erts/emulator/test/port_bif_SUITE_data/control_drv.c b/erts/emulator/test/port_bif_SUITE_data/control_drv.c index e9f57a887a..b937a8bb15 100644 --- a/erts/emulator/test/port_bif_SUITE_data/control_drv.c +++ b/erts/emulator/test/port_bif_SUITE_data/control_drv.c @@ -1,13 +1,15 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "erl_driver.h" static ErlDrvPort erlang_port; static ErlDrvData control_start(ErlDrvPort, char*); static void control_stop(ErlDrvData); -static void control_read(ErlDrvData, char*, int); -static int control_control(ErlDrvData, unsigned int, char*, int, char**, int); +static void control_read(ErlDrvData, char*, ErlDrvSizeT); +static ErlDrvSSizeT control_control(ErlDrvData, unsigned int, char*, + ErlDrvSizeT, char**, ErlDrvSizeT); static ErlDrvEntry control_driver_entry = { @@ -21,9 +23,19 @@ static ErlDrvEntry control_driver_entry = NULL, NULL, control_control, + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, NULL, NULL, - NULL }; DRIVER_INIT(control_drv) @@ -41,7 +53,7 @@ static ErlDrvData control_start(ErlDrvPort port,char *buf) return (ErlDrvData)port; } -static void control_read(ErlDrvData port, char *buf, int count) +static void control_read(ErlDrvData port, char *buf, ErlDrvSizeT count) { driver_output(erlang_port, buf, count); } @@ -51,8 +63,9 @@ static void control_stop(ErlDrvData port) erlang_port = (ErlDrvPort)-1; } -static int control_control(ErlDrvData port, unsigned command, char* buf, int count, - char** res, int res_size) +static ErlDrvSSizeT control_control(ErlDrvData port, unsigned command, + char* buf, ErlDrvSizeT count, + char** res, ErlDrvSizeT res_size) { switch (command) { case 'e': diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index f68e712268..fdc55a4cc5 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -35,7 +35,7 @@ self_exit/1, normal_suicide_exit/1, abnormal_suicide_exit/1, t_exit_2_catch/1, trap_exit_badarg/1, trap_exit_badarg_in_bif/1, exit_and_timeout/1, exit_twice/1, - t_process_info/1, process_info_other_msg/1, + t_process_info/1, process_info_other/1, process_info_other_msg/1, process_info_other_dist_msg/1, process_info_2_list/1, process_info_lock_reschedule/1, process_info_lock_reschedule2/1, @@ -64,7 +64,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [spawn_with_binaries, t_exit_1, {group, t_exit_2}, trap_exit_badarg, trap_exit_badarg_in_bif, - t_process_info, process_info_other_msg, + t_process_info, process_info_other, process_info_other_msg, process_info_other_dist_msg, process_info_2_list, process_info_lock_reschedule, process_info_lock_reschedule2, @@ -258,7 +258,9 @@ trap_exit_badarg() -> ?line Pid = fun_spawn(fun() -> bad_guy(kb_128()) end), ?line Garbage = kb_128(), ?line receive - {'EXIT', Pid, {badarg,[{erlang,abs,[Garbage]},{?MODULE,bad_guy,1}|_]}} -> + {'EXIT',Pid,{badarg,[{erlang,abs,[Garbage],Loc1}, + {?MODULE,bad_guy,1,Loc2}|_]}} + when is_list(Loc1), is_list(Loc2) -> ok; Other -> ?line ok = io:format("Bad EXIT message: ~P", [Other, 30]), @@ -410,7 +412,7 @@ etwice_high(Low) -> exit(Low, first), exit(Low, second). -%% Tests the process_info/1 BIF. +%% Tests the process_info/2 BIF. t_process_info(Config) when is_list(Config) -> ?line [] = process_info(self(), registered_name), ?line register(my_name, self()), @@ -418,13 +420,100 @@ t_process_info(Config) when is_list(Config) -> ?line {status, running} = process_info(self(), status), ?line {min_heap_size, 233} = process_info(self(), min_heap_size), ?line {min_bin_vheap_size, 46368} = process_info(self(), min_bin_vheap_size), - ?line {current_function, {?MODULE, t_process_info, 1}} = + ?line {current_function,{?MODULE,t_process_info,1}} = process_info(self(), current_function), + ?line {current_function,{?MODULE,t_process_info,1}} = + apply(erlang, process_info, [self(),current_function]), + + %% current_location and current_stacktrace + {Line1,Res1} = {?LINE,process_info(self(), current_location)}, + verify_loc(Line1, Res1), + {Line2,Res2} = {?LINE,apply(erlang, process_info, + [self(),current_location])}, + verify_loc(Line2, Res2), + pi_stacktrace([{?MODULE,t_process_info,1,?LINE}]), + ?line Gleader = group_leader(), ?line {group_leader, Gleader} = process_info(self(), group_leader), ?line {'EXIT',{badarg,_Info}} = (catch process_info('not_a_pid')), ok. +pi_stacktrace(Expected0) -> + {Line,Res} = {?LINE,erlang:process_info(self(), current_stacktrace)}, + {current_stacktrace,Stack} = Res, + Expected = [{?MODULE,pi_stacktrace,1,Line}|Expected0], + pi_stacktrace_1(Stack, Expected). + +pi_stacktrace_1([{M,F,A,Loc}|Stk], [{M,F,A,Line}|Exp]) -> + case Loc of + [] -> + %% No location info for some reason (+L, native code). + io:format("Missing location information for ~w:~w/~w", + [M,F,A]), + ok; + [_|_] -> + Line = proplists:get_value(line, Loc), + File = proplists:get_value(file, Loc), + File = ?MODULE_STRING ++ ".erl" + end, + pi_stacktrace_1(Stk, Exp); +pi_stacktrace_1([_|_], []) -> ok. + +verify_loc(Line, {current_location,{?MODULE,t_process_info=F,1=A,Loc}}) -> + case Loc of + [] -> + %% No location info for some reason (+L, native code). + io:format("Missing location information for ~w:~w/~w", + [?MODULE,F,A]), + ok; + [_|_] -> + Line = proplists:get_value(line, Loc), + File = proplists:get_value(file, Loc), + File = ?MODULE_STRING ++ ".erl" + end. + +process_info_other(Config) when is_list(Config) -> + Self = self(), + Pid = spawn_link(fun() -> process_info_looper(Self) end), + receive after 1 -> ok end, + pio_current_location(10000, Pid, 0, 0), + pio_current_stacktrace(). + +pio_current_location(0, _, Pi, Looper) -> + io:format("~w call(s) to erlang:process_info/2", [Pi]), + io:format("~w call(s) to ~w:process_info_looper/1", [Looper,?MODULE]); +pio_current_location(N, Pid, Pi, Looper) -> + erlang:yield(), + {current_location,Where} = process_info(Pid, current_location), + case Where of + {erlang,process_info,2,[]} -> + pio_current_location(N-1, Pid, Pi+1, Looper); + {?MODULE,process_info_looper,1,Loc} when is_list(Loc) -> + pio_current_location(N-1, Pid, Pi, Looper+1) + end. + +pio_current_stacktrace() -> + L = [begin + {current_stacktrace,Stk} = process_info(P, current_stacktrace), + {P,Stk} + end || P <- processes()], + [erlang:garbage_collect(P) || {P,_} <- L], + erlang:garbage_collect(), + [verify_stacktrace(Stk) || {_,Stk} <- L], + ok. + +verify_stacktrace([{M,F,A,Loc}|T]) + when is_atom(M), + is_atom(F), + is_integer(A), + is_list(Loc) -> + verify_stacktrace(T); +verify_stacktrace([]) -> ok. + +process_info_looper(Parent) -> + process_info(Parent, current_location), + process_info_looper(Parent). + %% Tests the process_info/1 BIF on another process with messages. process_info_other_msg(Config) when is_list(Config) -> Self = self(), diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index debb54579b..8931562828 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -55,7 +55,7 @@ scheduler_suspend/1, reader_groups/1]). --define(DEFAULT_TIMEOUT, ?t:minutes(10)). +-define(DEFAULT_TIMEOUT, ?t:minutes(15)). -define(MIN_SCHEDULER_TEST_TIMEOUT, ?t:minutes(1)). @@ -519,16 +519,18 @@ bound_loop(NS, N, M, Sched) -> bindings(Node, BindType) -> Parent = self(), Ref = make_ref(), - spawn_link(Node, - fun () -> - enable_internal_state(), - Res = (catch erts_debug:get_internal_state( - {fake_scheduler_bindings, BindType})), - Parent ! {Ref, Res} - end), + Pid = spawn_link(Node, + fun () -> + enable_internal_state(), + Res = (catch erts_debug:get_internal_state( + {fake_scheduler_bindings, + BindType})), + Parent ! {Ref, Res} + end), receive {Ref, Res} -> ?t:format("~p: ~p~n", [BindType, Res]), + unlink(Pid), Res end. @@ -1684,7 +1686,7 @@ do_it(Tracer, Low, Normal, High, Max, RedsPerSchedLimit) -> EndWait = now(), BalanceWait = timer:now_diff(EndWait,StartWait) div 1000, erlang:display({balance_wait, BalanceWait}), - Timeout = ?DEFAULT_TIMEOUT - ?t:seconds(10) - BalanceWait, + Timeout = ?DEFAULT_TIMEOUT - ?t:minutes(4) - BalanceWait, Res = case Timeout < ?MIN_SCHEDULER_TEST_TIMEOUT of true -> stop_work(Low, Normal, High, Max), diff --git a/erts/emulator/test/send_term_SUITE_data/send_term_drv.c b/erts/emulator/test/send_term_SUITE_data/send_term_drv.c index 165cce2e9d..b3feca79f0 100644 --- a/erts/emulator/test/send_term_SUITE_data/send_term_drv.c +++ b/erts/emulator/test/send_term_SUITE_data/send_term_drv.c @@ -24,7 +24,7 @@ static ErlDrvPort erlang_port; static ErlDrvData send_term_drv_start(ErlDrvPort port, char *command); static void send_term_drv_stop(ErlDrvData drv_data); -static void send_term_drv_run(ErlDrvData drv_data, char *buf, int len); +static void send_term_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); static int make_ext_term_list(ErlDrvTermData *td, int bad); @@ -39,6 +39,22 @@ static ErlDrvEntry send_term_drv_entry = { NULL, NULL, "send_term_drv", + NULL, + NULL, /* handle */ + NULL, /* control */ + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL, }; DRIVER_INIT(send_term_drv) @@ -64,7 +80,7 @@ static void send_term_drv_stop(ErlDrvData drv_data) static void output_term(ErlDrvTermData* msg, int len); static void fail_term(ErlDrvTermData* msg, int len, int line); -static void send_term_drv_run(ErlDrvData port, char *buf, int count) +static void send_term_drv_run(ErlDrvData port, char *buf, ErlDrvSizeT count) { char buf7[1024]; ErlDrvTermData spec[1024]; diff --git a/erts/emulator/test/sensitive_SUITE.erl b/erts/emulator/test/sensitive_SUITE.erl index 634df367ca..e073eab596 100644 --- a/erts/emulator/test/sensitive_SUITE.erl +++ b/erts/emulator/test/sensitive_SUITE.erl @@ -160,8 +160,7 @@ recv_trace(Config) when is_list(Config) -> ?line {messages,Messages} = process_info(Tracer, messages), [{trace,Parent,'receive',a}, {trace,Parent,'receive',{trace_delivered,_,_}}, - {trace,Parent,'receive',c}, - {trace,Parent,'receive',{trace_delivered,_,_}}] = Messages, + {trace,Parent,'receive',c}|_] = Messages, ?line unlink(Tracer), exit(Tracer, kill), ?line unlink(Sender), exit(Sender, kill), diff --git a/erts/emulator/test/system_profile_SUITE_data/echo_drv.c b/erts/emulator/test/system_profile_SUITE_data/echo_drv.c index d968ff06f9..e0b6ff804c 100644 --- a/erts/emulator/test/system_profile_SUITE_data/echo_drv.c +++ b/erts/emulator/test/system_profile_SUITE_data/echo_drv.c @@ -9,11 +9,9 @@ static EchoDrvData echo_drv_data, *echo_drv_data_p; static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command); static void echo_drv_stop(EchoDrvData *data_p); -static void echo_drv_output(EchoDrvData *data_p, char *buf, int len); +static void echo_drv_output(ErlDrvData drv_data, char *buf, + ErlDrvSizeT len); static void echo_drv_finish(void); -static int echo_drv_control(EchoDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen); static ErlDrvEntry echo_drv_entry = { NULL, /* init */ @@ -25,10 +23,21 @@ static ErlDrvEntry echo_drv_entry = { "echo_drv", echo_drv_finish, NULL, /* handle */ - echo_drv_control, + NULL, /* control */ NULL, /* timeout */ NULL, /* outputv */ - NULL /* ready_async */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL + }; DRIVER_INIT(echo_drv) @@ -51,16 +60,11 @@ static void echo_drv_stop(EchoDrvData *data_p) { echo_drv_data_p = NULL; } -static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) { +static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { + EchoDrvData* data_p = (EchoDrvData *) drv_data; driver_output(data_p->erlang_port, buf, len); } static void echo_drv_finish() { echo_drv_data_p = NULL; } - -static int echo_drv_control(EchoDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) { - return 0; -} diff --git a/erts/emulator/test/time_SUITE.erl b/erts/emulator/test/time_SUITE.erl index bd48a0a7db..4d12e3449c 100644 --- a/erts/emulator/test/time_SUITE.erl +++ b/erts/emulator/test/time_SUITE.erl @@ -32,6 +32,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, univ_to_local/1, local_to_univ/1, bad_univ_to_local/1, bad_local_to_univ/1, + univ_to_seconds/1, seconds_to_univ/1, consistency/1, now_unique/1, now_update/1, timestamp/1]). @@ -59,7 +60,9 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [univ_to_local, local_to_univ, local_to_univ_utc, - bad_univ_to_local, bad_local_to_univ, consistency, + bad_univ_to_local, bad_local_to_univ, + univ_to_seconds, seconds_to_univ, + consistency, {group, now}, timestamp]. groups() -> @@ -162,6 +165,30 @@ bad_test_local_to_univ([Local|Rest]) -> bad_test_local_to_univ([]) -> ok. + +%% Test universaltime to seconds conversions +univ_to_seconds(Config) when is_list(Config) -> + test_univ_to_seconds(ok_utc_seconds()). + +test_univ_to_seconds([{Datetime, Seconds}|DSs]) -> + io:format("universaltime = ~p -> seconds = ~p", [Datetime, Seconds]), + Seconds = erlang:universaltime_to_posixtime(Datetime), + test_univ_to_seconds(DSs); +test_univ_to_seconds([]) -> + ok. + +%% Test seconds to universaltime conversions +seconds_to_univ(Config) when is_list(Config) -> + test_seconds_to_univ(ok_utc_seconds()). + +test_seconds_to_univ([{Datetime, Seconds}|DSs]) -> + io:format("universaltime = ~p <- seconds = ~p", [Datetime, Seconds]), + Datetime = erlang:posixtime_to_universaltime(Seconds), + test_seconds_to_univ(DSs); +test_seconds_to_univ([]) -> + ok. + + %% Test that the the different time functions return %% consistent results. (See the test case for assumptions %% and limitations.) @@ -453,6 +480,32 @@ dst_dates() -> {1998, 06, 3}, {1999, 06, 4}]. +%% exakt utc {date(), time()} which corresponds to the same seconds since 1 jan 1970 +%% negative seconds are ok +%% generated with date --date='1979-05-28 12:30:35 UTC' +%s +ok_utc_seconds() -> [ + { {{1970, 1, 1},{ 0, 0, 0}}, 0 }, + { {{1970, 1, 1},{ 0, 0, 1}}, 1 }, + { {{1969,12,31},{23,59,59}}, -1 }, + { {{1920,12,31},{23,59,59}}, -1546300801 }, + { {{1600,02,19},{15,14,08}}, -11671807552 }, + { {{1979,05,28},{12,30,35}}, 296742635 }, + { {{1999,12,31},{23,59,59}}, 946684799 }, + { {{2000, 1, 1},{ 0, 0, 0}}, 946684800 }, + { {{2000, 1, 1},{ 0, 0, 1}}, 946684801 }, + + { {{2038, 1,19},{03,14,07}}, 2147483647 }, % Sint32 full - 1 + { {{2038, 1,19},{03,14,08}}, 2147483648 }, % Sint32 full + { {{2038, 1,19},{03,14,09}}, 2147483649 }, % Sint32 full + 1 + + { {{2106, 2, 7},{ 6,28,14}}, 4294967294 }, % Uint32 full 0xFFFFFFFF - 1 + { {{2106, 2, 7},{ 6,28,15}}, 4294967295 }, % Uint32 full 0xFFFFFFFF + { {{2106, 2, 7},{ 6,28,16}}, 4294967296 }, % Uint32 full 0xFFFFFFFF + 1 + { {{2012,12, 6},{16,28,08}}, 1354811288 }, + { {{2412,12, 6},{16,28,08}}, 13977592088 } + ]. + + %% The following dates should not be near the end or beginning of %% a month, because they will be used to test when the dates are %% different in UTC and local time. diff --git a/erts/emulator/test/trace_local_SUITE.erl b/erts/emulator/test/trace_local_SUITE.erl index 091e960610..32e2a98e3c 100644 --- a/erts/emulator/test/trace_local_SUITE.erl +++ b/erts/emulator/test/trace_local_SUITE.erl @@ -767,8 +767,8 @@ exception_test(Opts, Func0, Args0) -> end, ?line R1 = exc_slave(ExcOpts, Func, Args), - ?line Stack2 = [{?MODULE,exc_top,3},{?MODULE,slave,2}], - ?line Stack3 = [{?MODULE,exc,2}|Stack2], + ?line Stack2 = [{?MODULE,exc_top,3,[]},{?MODULE,slave,2,[]}], + ?line Stack3 = [{?MODULE,exc,2,[]}|Stack2], ?line Rs = case x_exc_top(ExcOpts, Func, Args) of % Emulation {crash,{Reason,Stack}}=R when is_list(Stack) -> @@ -789,21 +789,29 @@ exception_test(Opts, Func0, Args0) -> end, ?line expect({nm}). -exception_validate(R1, [R2|Rs]) -> +exception_validate(R0, Rs0) -> + R = clean_location(R0), + Rs = [clean_location(E) || E <- Rs0], + exception_validate_1(R, Rs). + +exception_validate_1(R1, [R2|Rs]) -> case [R1|R2] of [R|R] -> ok; - [{crash,{badarg,[{lists,reverse,[L1a,L1b]}|T]}}| - {crash,{badarg,[{lists,reverse,[L2a,L2b]}|T]}}] -> + [{crash,{badarg,[{lists,reverse,[L1a,L1b],_}|T]}}| + {crash,{badarg,[{lists,reverse,[L2a,L2b],_}|T]}}] -> same({crash,{badarg,[{lists,reverse, - [lists:reverse(L1b, L1a),[]]}|T]}}, + [lists:reverse(L1b, L1a),[]],[]}|T]}}, {crash,{badarg,[{lists,reverse, - [lists:reverse(L2b, L2a),[]]}|T]}}); + [lists:reverse(L2b, L2a),[]],[]}|T]}}); _ when is_list(Rs), Rs =/= [] -> exception_validate(R1, Rs) end. - +clean_location({crash,{Reason,Stk0}}) -> + Stk = [{M,F,A,[]} || {M,F,A,_} <- Stk0], + {crash,{Reason,Stk}}; +clean_location(Term) -> Term. %%% Tracee target functions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% @@ -1057,10 +1065,10 @@ x_exc_exception(_Rtt, M, F, _, Arity, CR) -> x_exc_stacktrace() -> x_exc_stacktrace(erlang:get_stacktrace()). %% Truncate stacktrace to below exc/2 -x_exc_stacktrace([{?MODULE,x_exc,4}|_]) -> []; -x_exc_stacktrace([{?MODULE,x_exc_func,4}|_]) -> []; -x_exc_stacktrace([{?MODULE,x_exc_body,4}|_]) -> []; -x_exc_stacktrace([{?MODULE,exc,2}|_]) -> []; +x_exc_stacktrace([{?MODULE,x_exc,4,_}|_]) -> []; +x_exc_stacktrace([{?MODULE,x_exc_func,4,_}|_]) -> []; +x_exc_stacktrace([{?MODULE,x_exc_body,4,_}|_]) -> []; +x_exc_stacktrace([{?MODULE,exc,2,_}|_]) -> []; x_exc_stacktrace([H|T]) -> [H|x_exc_stacktrace(T)]. diff --git a/erts/emulator/test/trace_port_SUITE_data/echo_drv.c b/erts/emulator/test/trace_port_SUITE_data/echo_drv.c index 15c4ca11fe..a8d4ede4fe 100644 --- a/erts/emulator/test/trace_port_SUITE_data/echo_drv.c +++ b/erts/emulator/test/trace_port_SUITE_data/echo_drv.c @@ -25,12 +25,14 @@ static EchoDrvData echo_drv_data, *echo_drv_data_p; **/ static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command); -static void echo_drv_stop(EchoDrvData *data_p); -static void echo_drv_output(EchoDrvData *data_p, char *buf, int len); +static void echo_drv_stop(ErlDrvData drv_data); +static void echo_drv_output(ErlDrvData drv_data, char *buf, + ErlDrvSizeT len); static void echo_drv_finish(void); -static int echo_drv_control(EchoDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen); +static ErlDrvSSizeT echo_drv_control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen); static ErlDrvEntry echo_drv_entry = { NULL, /* init */ @@ -45,11 +47,19 @@ static ErlDrvEntry echo_drv_entry = { echo_drv_control, NULL, /* timeout */ NULL, /* outputv */ - NULL /* ready_async */ + NULL, /* ready_async */ + NULL, + NULL, + NULL, + ERL_DRV_EXTENDED_MARKER, + ERL_DRV_EXTENDED_MAJOR_VERSION, + ERL_DRV_EXTENDED_MINOR_VERSION, + 0, + NULL, + NULL, + NULL }; - - /* ------------------------------------------------------------------------- ** Entry functions **/ @@ -75,7 +85,8 @@ static void echo_drv_stop(EchoDrvData *data_p) { echo_drv_data_p = NULL; } -static void echo_drv_output(EchoDrvData *data_p, char *buf, int len) { +static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) { + EchoDrvData* data_p = (EchoDrvData *) drv_data; driver_output(data_p->erlang_port, buf, len); switch (data_p->heavy) { case heavy_off: @@ -95,9 +106,11 @@ static void echo_drv_finish() { echo_drv_data_p = NULL; } -static int echo_drv_control(EchoDrvData *data_p, unsigned int command, - char *buf, int len, - char **rbuf, int rlen) { +static ErlDrvSSizeT echo_drv_control(ErlDrvData drv_data, + unsigned int command, + char *buf, ErlDrvSizeT len, + char **rbuf, ErlDrvSizeT rlen) { + EchoDrvData* data_p = (EchoDrvData *) drv_data; switch (command) { case 'h': data_p->heavy = heavy_set; |