diff options
Diffstat (limited to 'erts')
-rw-r--r-- | erts/configure.in | 15 | ||||
-rw-r--r-- | erts/doc/src/erlang.xml | 62 | ||||
-rw-r--r-- | erts/doc/src/zlib.xml | 60 | ||||
-rw-r--r-- | erts/emulator/beam/beam_bif_load.c | 30 | ||||
-rw-r--r-- | erts/emulator/beam/bif.tab | 8 | ||||
-rw-r--r-- | erts/emulator/beam/erl_gc.c | 40 | ||||
-rw-r--r-- | erts/emulator/beam/external.c | 49 | ||||
-rw-r--r-- | erts/emulator/beam/external.h | 1 | ||||
-rw-r--r-- | erts/emulator/test/binary_SUITE.erl | 16 | ||||
-rw-r--r-- | erts/emulator/test/code_SUITE.erl | 32 | ||||
-rw-r--r-- | erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c | 46 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 38 | ||||
-rw-r--r-- | erts/epmd/src/epmd.c | 6 | ||||
-rw-r--r-- | erts/epmd/src/epmd_cli.c | 5 | ||||
-rw-r--r-- | erts/epmd/src/epmd_srv.c | 3 | ||||
-rw-r--r-- | erts/example/matrix_nif.c | 85 | ||||
-rw-r--r-- | erts/lib_src/common/erl_misc_utils.c | 6 | ||||
-rw-r--r-- | erts/preloaded/ebin/zlib.beam | bin | 12148 -> 11876 bytes | |||
-rw-r--r-- | erts/preloaded/src/zlib.erl | 115 | ||||
-rw-r--r-- | erts/test/erlc_SUITE.erl | 25 |
20 files changed, 450 insertions, 192 deletions
diff --git a/erts/configure.in b/erts/configure.in index ffa68cd296..03e27c9dad 100644 --- a/erts/configure.in +++ b/erts/configure.in @@ -1673,6 +1673,15 @@ esac AC_C_BIGENDIAN +dnl fdatasync syscall (Unix only) +AC_CHECK_FUNCS([fdatasync]) + +dnl Find which C libraries are required to use fdatasync +dnl TODO: Remove check once SunOS >= 5.11 is required by erts. +dnl fdatasync requires linking against -lrt on SunOS <= 5.10. +dnl OpenSolaris 2009.06 is SunOS 5.11 and does not require -lrt. +AC_SEARCH_LIBS(fdatasync, [rt]) + dnl ---------------------------------------------------------------------- dnl Checks for library functions. dnl ---------------------------------------------------------------------- @@ -1860,12 +1869,6 @@ fi dnl Need by run_erl. AC_CHECK_FUNCS([openpty]) -dnl fdatasync syscall (Unix only) -AC_CHECK_FUNCS([fdatasync]) - -dnl Find which C libraries are required to use fdatasync -AC_SEARCH_LIBS(fdatasync, [rt]) - AC_CHECK_HEADERS(net/if_dl.h ifaddrs.h netpacket/packet.h) AC_CHECK_FUNCS([getifaddrs]) diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 7cfab0785d..84d4160e6a 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -518,6 +518,18 @@ </func> <func> + <name>check_old_code(Module) -> boolean()</name> + <fsummary>Check if a module has old code</fsummary> + <type> + <v>Module = atom()</v> + </type> + <desc> + <p>Returns <c>true</c> if the <c>Module</c> has old code, + and <c>false</c> otherwise.</p> + <p>See also <seealso marker="kernel:code">code(3)</seealso>.</p> + </desc> + </func> + <func> <name>check_process_code(Pid, Module) -> boolean()</name> <fsummary>Check if a process is executing old code for a module</fsummary> <type> @@ -1023,6 +1035,56 @@ b</pre> </desc> </func> <func> + <name>erlang:external_size(Term) -> integer() >= 0</name> + <fsummary>Calculate the maximum size for a term encoded in the Erlang + external term format</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Calculates, without doing the encoding, the maximum byte size for + a term encoded in the Erlang external term format. The following + condition applies always:</p> + <p> + <pre> +> <input>Size1 = byte_size(term_to_binary(Term)),</input> +> <input>Size2 = erlang:external_size(Term),</input> +> <input>true = Size1 =< Size2.</input> +true + </pre> + </p> + <p>This is equivalent to a call to: <code>erlang:external_size(Term, []) + </code></p> + </desc> + </func> + <func> + <name>erlang:external_size(Term, [Option]) -> integer() >= 0</name> + <fsummary>Calculate the maximum size for a term encoded in the Erlang + external term format</fsummary> + <type> + <v>Term = term()</v> + <v>Option = {minor_version, Version}</v> + </type> + <desc> + <p>Calculates, without doing the encoding, the maximum byte size for + a term encoded in the Erlang external term format. The following + condition applies always:</p> + <p> + <pre> +> <input>Size1 = byte_size(term_to_binary(Term, Options)),</input> +> <input>Size2 = erlang:external_size(Term, Options),</input> +> <input>true = Size1 =< Size2.</input> +true + </pre> + </p> + <p>The option <c>{minor_version, Version}</c> specifies how floats + are encoded. See + <seealso marker="#term_to_binary/2">term_to_binary/2</seealso> for + a more detailed description. + </p> + </desc> + </func> + <func> <name>float(Number) -> float()</name> <fsummary>Convert a number to a float</fsummary> <type> diff --git a/erts/doc/src/zlib.xml b/erts/doc/src/zlib.xml index 47a649af02..8917ab5c3a 100644 --- a/erts/doc/src/zlib.xml +++ b/erts/doc/src/zlib.xml @@ -378,31 +378,31 @@ unpack(Z, Compressed, Dict) -> <name name="crc32" arity="2"/> <fsummary>Calculate CRC</fsummary> <desc> - <p>Calculate the CRC checksum for <c><anno>Binary</anno></c>.</p> + <p>Calculate the CRC checksum for <c><anno>Data</anno></c>.</p> </desc> </func> <func> <name name="crc32" arity="3"/> <fsummary>Calculate CRC</fsummary> <desc> - <p>Update a running CRC checksum for <c><anno>Binary</anno></c>. - If <c><anno>Binary</anno></c> is the empty binary, this function returns + <p>Update a running CRC checksum for <c><anno>Data</anno></c>. + If <c><anno>Data</anno></c> is the empty binary or the empty iolist, this function returns the required initial value for the crc.</p> <pre> -Crc = lists:foldl(fun(Bin,Crc0) -> - zlib:crc32(Z, Crc0, Bin), - end, zlib:crc32(Z,<< >>), Bins)</pre> +Crc = lists:foldl(fun(Data,Crc0) -> + zlib:crc32(Z, Crc0, Data), + end, zlib:crc32(Z,<< >>), Datas)</pre> </desc> </func> <func> <name name="crc32_combine" arity="4"/> <fsummary>Combine two CRC's</fsummary> <desc> - <p>Combine two CRC checksums into one. For two binaries, - <c>Bin1</c> and <c>Bin2</c> with sizes of <c>Size1</c> and + <p>Combine two CRC checksums into one. For two binaries or iolists, + <c>Data1</c> and <c>Data2</c> with sizes of <c>Size1</c> and <c><anno>Size2</anno></c>, with CRC checksums <c><anno>CRC1</anno></c> and <c><anno>CRC2</anno></c>. <c>crc32_combine/4</c> returns the <c><anno>CRC</anno></c> - checksum of <c><<Bin1/binary,Bin2/binary>></c>, requiring + checksum of <c>[Data1,Data2]</c>, requiring only <c><anno>CRC1</anno></c>, <c><anno>CRC2</anno></c>, and <c><anno>Size2</anno></c>. </p> </desc> @@ -411,75 +411,75 @@ Crc = lists:foldl(fun(Bin,Crc0) -> <name name="adler32" arity="2"/> <fsummary>Calculate the adler checksum</fsummary> <desc> - <p>Calculate the Adler-32 checksum for <c><anno>Binary</anno></c>.</p> + <p>Calculate the Adler-32 checksum for <c><anno>Data</anno></c>.</p> </desc> </func> <func> <name name="adler32" arity="3"/> <fsummary>Calculate the adler checksum</fsummary> <desc> - <p>Update a running Adler-32 checksum for <c><anno>Binary</anno></c>. - If <c><anno>Binary</anno></c> is the empty binary, this function returns + <p>Update a running Adler-32 checksum for <c><anno>Data</anno></c>. + If <c><anno>Data</anno></c> is the empty binary or the empty iolist, this function returns the required initial value for the checksum.</p> <pre> -Crc = lists:foldl(fun(Bin,Crc0) -> - zlib:adler32(Z, Crc0, Bin), - end, zlib:adler32(Z,<< >>), Bins)</pre> +Crc = lists:foldl(fun(Data,Crc0) -> + zlib:adler32(Z, Crc0, Data), + end, zlib:adler32(Z,<< >>), Datas)</pre> </desc> </func> <func> <name name="adler32_combine" arity="4"/> <fsummary>Combine two Adler-32 checksums</fsummary> <desc> - <p>Combine two Adler-32 checksums into one. For two binaries, - <c>Bin1</c> and <c>Bin2</c> with sizes of <c>Size1</c> and + <p>Combine two Adler-32 checksums into one. For two binaries or iolists, + <c>Data1</c> and <c>Data2</c> with sizes of <c>Size1</c> and <c><anno>Size2</anno></c>, with Adler-32 checksums <c><anno>Adler1</anno></c> and <c><anno>Adler2</anno></c>. <c>adler32_combine/4</c> returns the <c><anno>Adler</anno></c> - checksum of <c><<Bin1/binary,Bin2/binary>></c>, requiring + checksum of <c>[Data1,Data2]</c>, requiring only <c><anno>Adler1</anno></c>, <c><anno>Adler2</anno></c>, and <c><anno>Size2</anno></c>. </p> </desc> </func> <func> <name name="compress" arity="1"/> - <fsummary>Compress a binary with standard zlib functionality</fsummary> + <fsummary>Compress data with standard zlib functionality</fsummary> <desc> - <p>Compress a binary (with zlib headers and checksum).</p> + <p>Compress data (with zlib headers and checksum).</p> </desc> </func> <func> <name name="uncompress" arity="1"/> - <fsummary>Uncompress a binary with standard zlib functionality</fsummary> + <fsummary>Uncompress data with standard zlib functionality</fsummary> <desc> - <p>Uncompress a binary (with zlib headers and checksum).</p> + <p>Uncompress data (with zlib headers and checksum).</p> </desc> </func> <func> <name name="zip" arity="1"/> - <fsummary>Compress a binary without the zlib headers</fsummary> + <fsummary>Compress data without the zlib headers</fsummary> <desc> - <p>Compress a binary (without zlib headers and checksum).</p> + <p>Compress data (without zlib headers and checksum).</p> </desc> </func> <func> <name name="unzip" arity="1"/> - <fsummary>Uncompress a binary without the zlib headers</fsummary> + <fsummary>Uncompress data without the zlib headers</fsummary> <desc> - <p>Uncompress a binary (without zlib headers and checksum).</p> + <p>Uncompress data (without zlib headers and checksum).</p> </desc> </func> <func> <name name="gzip" arity="1"/> - <fsummary>Compress a binary with gz header</fsummary> + <fsummary>Compress data with gz header</fsummary> <desc> - <p>Compress a binary (with gz headers and checksum).</p> + <p>Compress data (with gz headers and checksum).</p> </desc> </func> <func> <name name="gunzip" arity="1"/> - <fsummary>Uncompress a binary with gz header</fsummary> + <fsummary>Uncompress data with gz header</fsummary> <desc> - <p>Uncompress a binary (with gz headers and checksum).</p> + <p>Uncompress data (with gz headers and checksum).</p> </desc> </func> </funcs> diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index d76a7d8e9f..2561d7a630 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -162,6 +162,23 @@ BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3) return res; } +BIF_RETTYPE +check_old_code_1(BIF_ALIST_1) +{ + Module* modp; + + if (is_not_atom(BIF_ARG_1)) { + BIF_ERROR(BIF_P, BADARG); + } + modp = erts_get_module(BIF_ARG_1); + if (modp == NULL) { /* Doesn't exist. */ + BIF_RET(am_false); + } else if (modp->old_code == NULL) { /* No old code. */ + BIF_RET(am_false); + } + BIF_RET(am_true); +} + Eterm check_process_code_2(BIF_ALIST_2) { @@ -175,6 +192,13 @@ check_process_code_2(BIF_ALIST_2) Eterm res; if (internal_pid_index(BIF_ARG_1) >= erts_max_processes) goto error; + modp = erts_get_module(BIF_ARG_2); + if (modp == NULL) { /* Doesn't exist. */ + return am_false; + } else if (modp->old_code == NULL) { /* No old code. */ + return am_false; + } + #ifdef ERTS_SMP rp = erts_pid2proc_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, BIF_ARG_1, ERTS_PROC_LOCK_MAIN); @@ -188,7 +212,6 @@ check_process_code_2(BIF_ALIST_2) ERTS_BIF_YIELD2(bif_export[BIF_check_process_code_2], BIF_P, BIF_ARG_1, BIF_ARG_2); } - modp = erts_get_module(BIF_ARG_2); res = check_process_code(rp, modp); #ifdef ERTS_SMP if (BIF_P != rp) { @@ -412,11 +435,6 @@ check_process_code(Process* rp, Module* modp) #endif #define INSIDE(a) (start <= (a) && (a) < end) - if (modp == NULL) { /* Doesn't exist. */ - return am_false; - } else if (modp->old_code == NULL) { /* No old code. */ - return am_false; - } /* * Pick up limits for the module. diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab index d9dd80fa8b..831c0b1ce6 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -87,6 +87,8 @@ bif erlang:exit/2 bif 'erl.lang.proc':signal/2 ebif_signal_2 exit_2 bif erlang:external_size/1 bif 'erl.lang.term':external_size/1 ebif_external_size_1 +bif erlang:external_size/2 +bif 'erl.lang.term':external_size/2 ebif_external_size_2 ubif erlang:float/1 ubif 'erl.lang.number':to_float/1 ebif_to_float_1 float_1 bif erlang:float_to_list/1 @@ -802,6 +804,12 @@ bif prim_file:internal_name2native/1 bif prim_file:internal_native2name/1 bif prim_file:internal_normalize_utf8/1 bif file:native_name_encoding/0 + +# +# New in R14B04. +# +bif erlang:check_old_code/1 + # # Obsolete # diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 5edcd667e7..e3445bcdc5 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -100,14 +100,14 @@ static Uint combined_message_size(Process* p); static void remove_message_buffers(Process* p); static int major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl); static int minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl); -static void do_minor(Process *p, int new_sz, Eterm* objv, int nobj); +static void do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj); static Eterm* sweep_rootset(Rootset *rootset, Eterm* htop, char* src, Uint src_size); static Eterm* sweep_one_area(Eterm* n_hp, Eterm* n_htop, char* src, Uint src_size); static Eterm* sweep_one_heap(Eterm* heap_ptr, Eterm* heap_end, Eterm* htop, char* src, Uint src_size); static Eterm* collect_heap_frags(Process* p, Eterm* heap, Eterm* htop, Eterm* objv, int nobj); -static Uint adjust_after_fullsweep(Process *p, int size_before, +static Uint adjust_after_fullsweep(Process *p, Uint size_before, int need, Eterm *objv, int nobj); static void shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj); static void grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj); @@ -441,7 +441,15 @@ erts_garbage_collect(Process* p, int need, Eterm* objv, int nobj) p->last_old_htop = p->old_htop; #endif - return ((int) (HEAP_TOP(p) - HEAP_START(p)) / 10); + /* FIXME: This function should really return an Sint, i.e., a possibly + 64 bit wide signed integer, but that requires updating all the code + that calls it. For now, we just return INT_MAX if the result is too + large for an int. */ + { + Sint result = (HEAP_TOP(p) - HEAP_START(p)) / 10; + if (result >= INT_MAX) return INT_MAX; + else return (int) result; + } } /* @@ -599,7 +607,7 @@ erts_garbage_collect_literals(Process* p, Eterm* literals, Uint lit_size) char* area; Uint area_size; Eterm* old_htop; - int n; + Uint n; /* * Set GC state. @@ -731,7 +739,7 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl) * This improved Estone by more than 1200 estones on my computer * (Ultra Sparc 10). */ - size_t new_sz = erts_next_heap_size(HEAP_TOP(p) - HEAP_START(p), 1); + Uint new_sz = erts_next_heap_size(HEAP_TOP(p) - HEAP_START(p), 1); /* Create new, empty old_heap */ n_old = (Eterm *) ERTS_HEAP_ALLOC(ERTS_ALC_T_OLD_HEAP, @@ -871,12 +879,12 @@ minor_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl) #endif /* HIPE */ static void -do_minor(Process *p, int new_sz, Eterm* objv, int nobj) +do_minor(Process *p, Uint new_sz, Eterm* objv, int nobj) { Rootset rootset; /* Rootset for GC (stack, dictionary, etc). */ Roots* roots; Eterm* n_htop; - int n; + Uint n; Eterm* ptr; Eterm val; Eterm gval; @@ -1079,14 +1087,14 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl) { Rootset rootset; Roots* roots; - int size_before; + Uint size_before; Eterm* n_heap; Eterm* n_htop; char* src = (char *) HEAP_START(p); Uint src_size = (char *) HEAP_TOP(p) - src; char* oh = (char *) OLD_HEAP(p); Uint oh_size = (char *) OLD_HTOP(p) - oh; - int n; + Uint n; Uint new_sz; Uint fragments = MBUF_SIZE(p) + combined_message_size(p); ErlMessage *msgp; @@ -1312,10 +1320,10 @@ major_collection(Process* p, int need, Eterm* objv, int nobj, Uint *recl) } static Uint -adjust_after_fullsweep(Process *p, int size_before, int need, Eterm *objv, int nobj) +adjust_after_fullsweep(Process *p, Uint size_before, int need, Eterm *objv, int nobj) { - int wanted, sz, size_after, need_after; - int stack_size = STACK_SZ_ON_HEAP(p); + Uint wanted, sz, size_after, need_after; + Uint stack_size = STACK_SZ_ON_HEAP(p); Uint reclaimed_now; size_after = (HEAP_TOP(p) - HEAP_START(p)); @@ -1915,8 +1923,8 @@ static void grow_new_heap(Process *p, Uint new_sz, Eterm* objv, int nobj) { Eterm* new_heap; - int heap_size = HEAP_TOP(p) - HEAP_START(p); - int stack_size = p->hend - p->stop; + Uint heap_size = HEAP_TOP(p) - HEAP_START(p); + Uint stack_size = p->hend - p->stop; Sint offs; ASSERT(HEAP_SIZE(p) < new_sz); @@ -1954,10 +1962,10 @@ static void shrink_new_heap(Process *p, Uint new_sz, Eterm *objv, int nobj) { Eterm* new_heap; - int heap_size = HEAP_TOP(p) - HEAP_START(p); + Uint heap_size = HEAP_TOP(p) - HEAP_START(p); Sint offs; - int stack_size = p->hend - p->stop; + Uint stack_size = p->hend - p->stop; ASSERT(new_sz < p->heap_sz); sys_memmove(p->heap + new_sz - stack_size, p->stop, stack_size * diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index 1a102f7187..6953e7fe7d 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -459,6 +459,12 @@ Uint erts_encode_ext_size(Eterm term) + 1 /* VERSION_MAGIC */; } +Uint erts_encode_ext_size_2(Eterm term, unsigned dflags) +{ + return encode_size_struct2(NULL, term, TERM_TO_BINARY_DFLAGS|dflags) + + 1 /* VERSION_MAGIC */; +} + Uint erts_encode_ext_size_ets(Eterm term) { return encode_size_struct2(NULL, term, TERM_TO_BINARY_DFLAGS|DFLAGS_INTERNAL_TAGS); @@ -1262,6 +1268,49 @@ external_size_1(Process* p, Eterm Term) } Eterm +external_size_2(Process* p, Eterm Term, Eterm Flags) +{ + Uint size; + Uint flags = TERM_TO_BINARY_DFLAGS; + + while (is_list(Flags)) { + Eterm arg = CAR(list_val(Flags)); + Eterm* tp; + + if (is_tuple(arg) && *(tp = tuple_val(arg)) == make_arityval(2)) { + if (tp[1] == am_minor_version && is_small(tp[2])) { + switch (signed_val(tp[2])) { + case 0: + break; + case 1: + flags |= DFLAG_NEW_FLOATS; + break; + default: + goto error; + } + } else { + goto error; + } + } else { + error: + BIF_ERROR(p, BADARG); + } + Flags = CDR(list_val(Flags)); + } + if (is_not_nil(Flags)) { + goto error; + } + + size = erts_encode_ext_size_2(Term, flags); + if (IS_USMALL(0, size)) { + BIF_RET(make_small(size)); + } else { + Eterm* hp = HAlloc(p, BIG_UINT_HEAP_SIZE); + BIF_RET(uint_to_big(size, hp)); + } +} + +Eterm erts_term_to_binary(Process* p, Eterm Term, int level, Uint flags) { Uint size; diff --git a/erts/emulator/beam/external.h b/erts/emulator/beam/external.h index d8287b96a4..72fe74baf2 100644 --- a/erts/emulator/beam/external.h +++ b/erts/emulator/beam/external.h @@ -160,6 +160,7 @@ Uint erts_encode_dist_ext_size(Eterm, Uint32, ErtsAtomCacheMap *); void erts_encode_dist_ext(Eterm, byte **, Uint32, ErtsAtomCacheMap *); Uint erts_encode_ext_size(Eterm); +Uint erts_encode_ext_size_2(Eterm, unsigned); Uint erts_encode_ext_size_ets(Eterm); void erts_encode_ext(Eterm, byte **); byte* erts_encode_ext_ets(Eterm, byte *, struct erl_off_heap_header** ext_off_heap); diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl index 4e82381fba..fed5854112 100644 --- a/erts/emulator/test/binary_SUITE.erl +++ b/erts/emulator/test/binary_SUITE.erl @@ -478,6 +478,11 @@ terms(Config) when is_list(Config) -> Sz when is_integer(Sz), size(Bin) =< Sz -> ok end, + Bin1 = term_to_binary(Term, [{minor_version, 1}]), + case erlang:external_size(Bin1, [{minor_version, 1}]) of + Sz1 when is_integer(Sz1), size(Bin1) =< Sz1 -> + ok + end, Term = binary_to_term(Bin), Term = binary_to_term(Bin, [safe]), Unaligned = make_unaligned_sub_binary(Bin), @@ -510,7 +515,12 @@ terms_float(Config) when is_list(Config) -> Term = binary_to_term(Bin0), Bin1 = term_to_binary(Term, [{minor_version,1}]), Term = binary_to_term(Bin1), - true = size(Bin1) < size(Bin0) + true = size(Bin1) < size(Bin0), + Size0 = erlang:external_size(Term), + Size00 = erlang:external_size(Term, [{minor_version, 0}]), + Size1 = erlang:external_size(Term, [{minor_version, 1}]), + true = (Size0 =:= Size00), + true = Size1 < Size0 end). external_size(Config) when is_list(Config) -> @@ -526,7 +536,9 @@ external_size(Config) when is_list(Config) -> io:format(" Aligned size: ~p\n", [Sz1]), io:format("Unaligned size: ~p\n", [Sz2]), ?line ?t:fail() - end. + end, + ?line erlang:external_size(Bin) =:= erlang:external_size(Bin, [{minor_version, 1}]), + ?line erlang:external_size(Unaligned) =:= erlang:external_size(Unaligned, [{minor_version, 1}]). external_size_1(Term, Size0, Limit) when Size0 < Limit -> case erlang:external_size(Term) of diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index a062cea117..29cbdedd17 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -20,7 +20,9 @@ -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,t_check_process_code/1,t_check_process_code_ets/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]). @@ -31,7 +33,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [new_binary_types, t_check_process_code, - t_check_process_code_ets, external_fun, get_chunk, + 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]. @@ -248,6 +250,32 @@ fun_refc(F) -> Count. +%% Test the erlang:check_old_code/1 BIF. +t_check_old_code(Config) when is_list(Config) -> + ?line Data = ?config(data_dir, Config), + ?line File = filename:join(Data, "my_code_test"), + + ?line erlang:purge_module(my_code_test), + ?line erlang:delete_module(my_code_test), + ?line catch erlang:purge_module(my_code_test), + + ?line false = erlang:check_old_code(my_code_test), + + ?line {ok,my_code_test,Code} = compile:file(File, [binary]), + ?line {module,my_code_test} = code:load_binary(my_code_test, File, Code), + + ?line false = erlang:check_old_code(my_code_test), + ?line {module,my_code_test} = code:load_binary(my_code_test, File, Code), + ?line true = erlang:check_old_code(my_code_test), + + ?line true = erlang:purge_module(my_code_test), + ?line true = erlang:delete_module(my_code_test), + ?line true = erlang:purge_module(my_code_test), + + ?line {'EXIT',_} = (catch erlang:check_old_code([])), + + ok. + 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), diff --git a/erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c b/erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c index 818023211c..0e4065c26b 100644 --- a/erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c +++ b/erts/emulator/test/mtx_SUITE_data/mtx_SUITE.c @@ -552,13 +552,19 @@ create_rwlock(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) static ERL_NIF_TERM rwlock_op(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - rwlock_resource_t *rwlr; + /* + * Use a union for pointer type conversion to avoid compiler warnings + * about strict-aliasing violations with gcc-4.1. gcc >= 4.2 does not + * emit the warning. + * TODO: Reconsider use of union once gcc-4.1 is obsolete? + */ + union { void* vp; rwlock_resource_t *p; } rwlr; int blocking, write, wait_locked, wait_unlocked; if (argc != 5) goto badarg; - if (!enif_get_resource(env, argv[0], enif_priv_data(env), (void **) &rwlr)) + if (!enif_get_resource(env, argv[0], enif_priv_data(env), &rwlr.vp)) goto badarg; blocking = get_bool(env, argv[1]); @@ -581,22 +587,22 @@ rwlock_op(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) if (write) { if (blocking) - RWMUTEX_WLOCK(rwlr->rwlock); + RWMUTEX_WLOCK(rwlr.p->rwlock); else - while (EBUSY == RWMUTEX_TRYWLOCK(rwlr->rwlock)); - if (rwlr->lock_check) { - ASSERT(!ATOMIC_READ(&rwlr->is_locked)); - ATOMIC_SET(&rwlr->is_locked, -1); + while (EBUSY == RWMUTEX_TRYWLOCK(rwlr.p->rwlock)); + if (rwlr.p->lock_check) { + ASSERT(!ATOMIC_READ(&rwlr.p->is_locked)); + ATOMIC_SET(&rwlr.p->is_locked, -1); } } else { if (blocking) - RWMUTEX_RLOCK(rwlr->rwlock); + RWMUTEX_RLOCK(rwlr.p->rwlock); else - while (EBUSY == RWMUTEX_TRYRLOCK(rwlr->rwlock)); - if (rwlr->lock_check) { - ASSERT(ATOMIC_READ(&rwlr->is_locked) >= 0); - ATOMIC_INC(&rwlr->is_locked); + while (EBUSY == RWMUTEX_TRYRLOCK(rwlr.p->rwlock)); + if (rwlr.p->lock_check) { + ASSERT(ATOMIC_READ(&rwlr.p->is_locked) >= 0); + ATOMIC_INC(&rwlr.p->is_locked); } } @@ -604,18 +610,18 @@ rwlock_op(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) milli_sleep(wait_locked); if (write) { - if (rwlr->lock_check) { - ASSERT(ATOMIC_READ(&rwlr->is_locked) == -1); - ATOMIC_SET(&rwlr->is_locked, 0); + if (rwlr.p->lock_check) { + ASSERT(ATOMIC_READ(&rwlr.p->is_locked) == -1); + ATOMIC_SET(&rwlr.p->is_locked, 0); } - RWMUTEX_WUNLOCK(rwlr->rwlock); + RWMUTEX_WUNLOCK(rwlr.p->rwlock); } else { - if (rwlr->lock_check) { - ASSERT(ATOMIC_READ(&rwlr->is_locked) > 0); - ATOMIC_DEC(&rwlr->is_locked); + if (rwlr.p->lock_check) { + ASSERT(ATOMIC_READ(&rwlr.p->is_locked) > 0); + ATOMIC_DEC(&rwlr.p->is_locked); } - RWMUTEX_RUNLOCK(rwlr->rwlock); + RWMUTEX_RUNLOCK(rwlr.p->rwlock); } if (wait_unlocked) diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index 00a1365bc3..92f1bab8dd 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -41,7 +41,18 @@ typedef struct CallInfo* call_history; NifModPrivData* nif_mod; union { ErlNifResourceType* t; long l; } rt_arr[2]; -}PrivData; +} PrivData; + +/* + * Use a union for pointer type conversion to avoid compiler warnings + * about strict-aliasing violations with gcc-4.1. gcc >= 4.2 does not + * emit the warning. + * TODO: Reconsider use of union once gcc-4.1 is obsolete? + */ +typedef union { + void* vp; + struct make_term_info* p; +} mti_t; void add_call(ErlNifEnv* env, PrivData* data, const char* func_name) { @@ -707,7 +718,7 @@ static ERL_NIF_TERM get_resource_type(ErlNifEnv* env, int argc, const ERL_NIF_TE static ERL_NIF_TERM alloc_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary data_bin; - union { ErlNifResourceType* t; long l;} type; + union { ErlNifResourceType* t; long l; } type; union { void* p; long l;} data; if (!enif_get_long(env, argv[0], &type.l) || !enif_inspect_binary(env, argv[1], &data_bin) @@ -731,7 +742,7 @@ static ERL_NIF_TERM make_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM a static ERL_NIF_TERM make_new_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary data_bin; - union { ErlNifResourceType* t; long l;} type; + union { ErlNifResourceType* t; long l; } type; void* data; ERL_NIF_TERM ret; if (!enif_get_long(env, argv[0], &type.l) @@ -749,7 +760,7 @@ static ERL_NIF_TERM make_new_resource(ErlNifEnv* env, int argc, const ERL_NIF_TE static ERL_NIF_TERM make_new_resource_binary(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifBinary data_bin; - union { struct binary_resource* p; void* vp; long l;} br; + union { struct binary_resource* p; void* vp; long l; } br; void* buf; ERL_NIF_TERM ret; if (!enif_inspect_binary(env, argv[0], &data_bin) @@ -1269,10 +1280,7 @@ static void msgenv_dtor(ErlNifEnv* env, void* obj) static ERL_NIF_TERM clear_msgenv(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - union { - void* vp; - struct make_term_info* p; - }mti; + mti_t mti; if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp)) { return enif_make_badarg(env); } @@ -1285,7 +1293,7 @@ static ERL_NIF_TERM clear_msgenv(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar static ERL_NIF_TERM grow_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - union { void* vp; struct make_term_info* p; }mti; + mti_t mti; ERL_NIF_TERM term; if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp) || (argc>2 && !enif_get_uint(env,argv[2], &mti.p->n))) { @@ -1301,7 +1309,7 @@ static ERL_NIF_TERM grow_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ static ERL_NIF_TERM send_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - union { void* vp; struct make_term_info* p; }mti; + mti_t mti; ErlNifPid to; ERL_NIF_TERM copy; int res; @@ -1316,7 +1324,7 @@ static ERL_NIF_TERM send_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ static ERL_NIF_TERM send3_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - union { void* vp; struct make_term_info* p; }mti; + mti_t mti; ErlNifPid to; ERL_NIF_TERM copy; int res; @@ -1334,7 +1342,7 @@ static ERL_NIF_TERM send3_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv void* threaded_sender(void *arg) { - union { void* vp; struct make_term_info* p; }mti; + mti_t mti; mti.vp = arg; enif_mutex_lock(mti.p->mtx); @@ -1349,7 +1357,7 @@ void* threaded_sender(void *arg) static ERL_NIF_TERM send_blob_thread(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - union { void* vp; struct make_term_info* p; }mti; + mti_t mti; ERL_NIF_TERM copy; if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp) || !enif_get_local_pid(env,argv[1], &mti.p->to_pid)) { @@ -1375,7 +1383,7 @@ static ERL_NIF_TERM send_blob_thread(ErlNifEnv* env, int argc, const ERL_NIF_TER static ERL_NIF_TERM join_send_thread(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - union { void* vp; struct make_term_info* p; }mti; + mti_t mti; int err; if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp)) { return enif_make_badarg(env); @@ -1392,7 +1400,7 @@ static ERL_NIF_TERM join_send_thread(ErlNifEnv* env, int argc, const ERL_NIF_TER static ERL_NIF_TERM copy_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { - union { void* vp; struct make_term_info* p; }mti; + mti_t mti; if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp)) { return enif_make_badarg(env); } diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c index 08576d923f..2267f9b12b 100644 --- a/erts/epmd/src/epmd.c +++ b/erts/epmd/src/epmd.c @@ -324,7 +324,11 @@ static void run_daemon(EpmdVars *g) } /* move cwd to root to make sure we are not on a mounted filesystem */ - chdir("/"); + if (chdir("/") < 0) + { + dbg_perror(g,"epmd: chdir() failed"); + epmd_cleanup_exit(g,1); + } umask(0); diff --git a/erts/epmd/src/epmd_cli.c b/erts/epmd/src/epmd_cli.c index ac55ba6bb6..2377c0dfe7 100644 --- a/erts/epmd/src/epmd_cli.c +++ b/erts/epmd/src/epmd_cli.c @@ -104,7 +104,10 @@ void epmd_call(EpmdVars *g,int what) fd = conn_to_epmd(g); put_int16(1,buf); buf[2] = what; - write(fd,buf,3); + if (write(fd, buf, 3) != 3) { + printf("epmd: Can't write to epmd\n"); + epmd_cleanup_exit(g,1); + } if (read(fd,(char *)&i,4) != 4) { if (!g->silent) printf("epmd: no response from local epmd\n"); diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c index 5debae26b6..da575affa1 100644 --- a/erts/epmd/src/epmd_srv.c +++ b/erts/epmd/src/epmd_srv.c @@ -102,7 +102,8 @@ void run(EpmdVars *g) dbg_printf(g,2,"try to initiate listening port %d", g->port); - if (g->addresses != NULL) + if (g->addresses != NULL && /* String contains non-separator characters if: */ + g->addresses[strspn(g->addresses," ,")] != '\000') { char *tmp; char *token; diff --git a/erts/example/matrix_nif.c b/erts/example/matrix_nif.c index c5e01dade5..43f9526ae3 100644 --- a/erts/example/matrix_nif.c +++ b/erts/example/matrix_nif.c @@ -31,7 +31,19 @@ typedef struct unsigned nrows; unsigned ncols; double* data; -}Matrix; +} Matrix; + +/* + * Use a union for pointer type conversion to avoid compiler warnings + * about strict-aliasing violations with gcc-4.1. gcc >= 4.2 does not + * emit the warning. + * TODO: Reconsider use of union once gcc-4.1 is obsolete? + */ +typedef union +{ + void* vp; + Matrix* p; +} mx_t; #define POS(MX, ROW, COL) ((MX)->data[(ROW)* (MX)->ncols + (COL)]) @@ -44,8 +56,9 @@ static ErlNifResourceType* resource_type = NULL; static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { - ErlNifResourceType* rt = enif_open_resource_type(env, "matrix_nif_example", - matrix_dtor, + ErlNifResourceType* rt = enif_open_resource_type(env, NULL, + "matrix_nif_example", + matrix_dtor, ERL_NIF_RT_CREATE, NULL); if (rt == NULL) { return -1; @@ -90,12 +103,12 @@ static ERL_NIF_TERM create(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) } ret = enif_make_resource(env, mx); - enif_release_resource(env, mx); + enif_release_resource(mx); return ret; badarg: if (mx != NULL) { - enif_release_resource(env,mx); + enif_release_resource(mx); } return enif_make_badarg(env); } @@ -104,14 +117,14 @@ badarg: static ERL_NIF_TERM pos(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { /* pos(Matrix, Row, Column) -> float() */ - Matrix* mx; + mx_t mx; unsigned i, j; - if (!enif_get_resource(env, argv[0], resource_type, (void**)&mx) || - !enif_get_uint(env, argv[1], &i) || (--i >= mx->nrows) || - !enif_get_uint(env, argv[2], &j) || (--j >= mx->ncols)) { + if (!enif_get_resource(env, argv[0], resource_type, &mx.vp) || + !enif_get_uint(env, argv[1], &i) || (--i >= mx.p->nrows) || + !enif_get_uint(env, argv[2], &j) || (--j >= mx.p->ncols)) { return enif_make_badarg(env); } - return enif_make_double(env, POS(mx, i,j)); + return enif_make_double(env, POS(mx.p, i,j)); } static ERL_NIF_TERM add(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -119,37 +132,38 @@ static ERL_NIF_TERM add(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) /* add(Matrix_A, Matrix_B) -> Matrix_Sum */ unsigned i, j; ERL_NIF_TERM ret; - Matrix* mxA = NULL; - Matrix* mxB = NULL; - Matrix* mxS = NULL; + mx_t mxA, mxB, mxS; + mxA.p = NULL; + mxB.p = NULL; + mxS.p = NULL; - if (!enif_get_resource(env, argv[0], resource_type, (void**)&mxA) || - !enif_get_resource(env, argv[1], resource_type, (void**)&mxB) || - mxA->nrows != mxB->nrows || - mxB->ncols != mxB->ncols) { + if (!enif_get_resource(env, argv[0], resource_type, &mxA.vp) || + !enif_get_resource(env, argv[1], resource_type, &mxB.vp) || + mxA.p->nrows != mxB.p->nrows || + mxB.p->ncols != mxB.p->ncols) { return enif_make_badarg(env); } - mxS = alloc_matrix(env, mxA->nrows, mxA->ncols); - for (i = 0; i < mxA->nrows; i++) { - for (j = 0; j < mxA->ncols; j++) { - POS(mxS, i, j) = POS(mxA, i, j) + POS(mxB, i, j); + mxS.p = alloc_matrix(env, mxA.p->nrows, mxA.p->ncols); + for (i = 0; i < mxA.p->nrows; i++) { + for (j = 0; j < mxA.p->ncols; j++) { + POS(mxS.p, i, j) = POS(mxA.p, i, j) + POS(mxB.p, i, j); } } - ret = enif_make_resource(env, mxS); - enif_release_resource(env, mxS); + ret = enif_make_resource(env, mxS.p); + enif_release_resource(mxS.p); return ret; } static ERL_NIF_TERM size_of(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { /* size(Matrix) -> {Nrows, Ncols} */ - Matrix* mx; - if (!enif_get_resource(env, argv[0], resource_type, (void**)&mx)) { + mx_t mx; + if (!enif_get_resource(env, argv[0], resource_type, &mx.vp)) { return enif_make_badarg(env); } - return enif_make_tuple2(env, enif_make_uint(env, mx->nrows), - enif_make_uint(env, mx->ncols)); + return enif_make_tuple2(env, enif_make_uint(env, mx.p->nrows), + enif_make_uint(env, mx.p->ncols)); } static ERL_NIF_TERM to_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -157,16 +171,17 @@ static ERL_NIF_TERM to_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) /* to_term(Matrix) -> [[first row], [second row], ...,[last row]] */ unsigned i, j; ERL_NIF_TERM res; - Matrix* mx = NULL; + mx_t mx; + mx.p = NULL; - if (!enif_get_resource(env, argv[0], resource_type, (void**)&mx)) { + if (!enif_get_resource(env, argv[0], resource_type, &mx.vp)) { return enif_make_badarg(env); } res = enif_make_list(env, 0); - for (i = mx->nrows; i-- > 0; ) { + for (i = mx.p->nrows; i-- > 0; ) { ERL_NIF_TERM row = enif_make_list(env, 0); - for (j = mx->ncols; j-- > 0; ) { - row = enif_make_list_cell(env, enif_make_double(env, POS(mx,i,j)), + for (j = mx.p->ncols; j-- > 0; ) { + row = enif_make_list_cell(env, enif_make_double(env, POS(mx.p,i,j)), row); } res = enif_make_list_cell(env, row, res); @@ -183,17 +198,17 @@ static int get_number(ErlNifEnv* env, ERL_NIF_TERM term, double* dp) static Matrix* alloc_matrix(ErlNifEnv* env, unsigned nrows, unsigned ncols) { - Matrix* mx = enif_alloc_resource(env, resource_type, sizeof(Matrix)); + Matrix* mx = enif_alloc_resource(resource_type, sizeof(Matrix)); mx->nrows = nrows; mx->ncols = ncols; - mx->data = enif_alloc(env, nrows*ncols*sizeof(double)); + mx->data = enif_alloc(nrows*ncols*sizeof(double)); return mx; } static void matrix_dtor(ErlNifEnv* env, void* obj) { Matrix* mx = (Matrix*) obj; - enif_free(env, mx->data); + enif_free(mx->data); mx->data = NULL; } diff --git a/erts/lib_src/common/erl_misc_utils.c b/erts/lib_src/common/erl_misc_utils.c index 35b148990a..5e94ff19db 100644 --- a/erts/lib_src/common/erl_misc_utils.c +++ b/erts/lib_src/common/erl_misc_utils.c @@ -55,6 +55,12 @@ # ifdef HAVE_UNISTD_H # include <unistd.h> # endif +# if defined(_SC_NPROC_CONF) && !defined(_SC_NPROCESSORS_CONF) +# define _SC_NPROCESSORS_CONF _SC_NPROC_CONF +# endif +# if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN) +# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN +# endif # if (defined(NO_SYSCONF) || !defined(_SC_NPROCESSORS_CONF)) # ifdef HAVE_SYS_SYSCTL_H # include <sys/sysctl.h> diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam Binary files differindex d400269ed0..cda53f7692 100644 --- a/erts/preloaded/ebin/zlib.beam +++ b/erts/preloaded/ebin/zlib.beam diff --git a/erts/preloaded/src/zlib.erl b/erts/preloaded/src/zlib.erl index 6cc7b27114..210532edac 100644 --- a/erts/preloaded/src/zlib.erl +++ b/erts/preloaded/src/zlib.erl @@ -173,7 +173,7 @@ deflateInit(Z, Level, Method, WindowBits, MemLevel, Strategy) -> -spec deflateSetDictionary(Z, Dictionary) -> Adler32 when Z :: zstream(), - Dictionary :: binary(), + Dictionary :: iodata(), Adler32 :: integer(). deflateSetDictionary(Z, Dictionary) -> call(Z, ?DEFLATE_SETDICT, Dictionary). @@ -232,7 +232,7 @@ inflateInit(Z, WindowBits) -> -spec inflateSetDictionary(Z, Dictionary) -> 'ok' when Z :: zstream(), - Dictionary :: binary(). + Dictionary :: iodata(). inflateSetDictionary(Z, Dictionary) -> call(Z, ?INFLATE_SETDICT, Dictionary). @@ -283,38 +283,36 @@ getBufSize(Z) -> crc32(Z) -> call(Z, ?CRC32_0, []). --spec crc32(Z, Binary) -> CRC when +-spec crc32(Z, Data) -> CRC when Z :: zstream(), - Binary :: binary(), + Data :: iodata(), CRC :: integer(). -crc32(Z, Binary) -> - call(Z, ?CRC32_1, Binary). +crc32(Z, Data) -> + call(Z, ?CRC32_1, Data). --spec crc32(Z, PrevCRC, Binary) -> CRC when +-spec crc32(Z, PrevCRC, Data) -> CRC when Z :: zstream(), PrevCRC :: integer(), - Binary :: binary(), + Data :: iodata(), CRC :: integer(). -crc32(Z, CRC, Binary) when is_binary(Binary), is_integer(CRC) -> - call(Z, ?CRC32_2, <<CRC:32, Binary/binary>>); -crc32(_Z, _CRC, _Binary) -> - erlang:error(badarg). +crc32(Z, CRC, Data) -> + call(Z, ?CRC32_2, [<<CRC:32>>, Data]). --spec adler32(Z, Binary) -> CheckSum when +-spec adler32(Z, Data) -> CheckSum when Z :: zstream(), - Binary :: binary(), + Data :: iodata(), CheckSum :: integer(). -adler32(Z, Binary) -> - call(Z, ?ADLER32_1, Binary). +adler32(Z, Data) -> + call(Z, ?ADLER32_1, Data). --spec adler32(Z, PrevAdler, Binary) -> CheckSum when +-spec adler32(Z, PrevAdler, Data) -> CheckSum when Z :: zstream(), PrevAdler :: integer(), - Binary :: binary(), + Data :: iodata(), CheckSum :: integer(). -adler32(Z, Adler, Binary) when is_binary(Binary), is_integer(Adler) -> - call(Z, ?ADLER32_2, <<Adler:32, Binary/binary>>); -adler32(_Z, _Adler, _Binary) -> +adler32(Z, Adler, Data) when is_integer(Adler) -> + call(Z, ?ADLER32_2, [<<Adler:32>>, Data]); +adler32(_Z, _Adler, _Data) -> erlang:error(badarg). -spec crc32_combine(Z, CRC1, CRC2, Size2) -> CRC when @@ -346,76 +344,83 @@ getQSize(Z) -> call(Z, ?GET_QSIZE, []). %% compress/uncompress zlib with header --spec compress(Binary) -> Compressed when - Binary :: binary(), +-spec compress(Data) -> Compressed when + Data :: iodata(), Compressed :: binary(). -compress(Binary) -> +compress(Data) -> Z = open(), deflateInit(Z, default), - Bs = deflate(Z, Binary,finish), + Bs = deflate(Z, Data, finish), deflateEnd(Z), close(Z), - list_to_binary(Bs). + iolist_to_binary(Bs). --spec uncompress(Binary) -> Decompressed when - Binary :: binary(), +-spec uncompress(Data) -> Decompressed when + Data :: iodata(), Decompressed :: binary(). -uncompress(Binary) when byte_size(Binary) >= 8 -> - Z = open(), - inflateInit(Z), - Bs = inflate(Z, Binary), - inflateEnd(Z), - close(Z), - list_to_binary(Bs); -uncompress(Binary) when is_binary(Binary) -> erlang:error(data_error); -uncompress(_) -> erlang:error(badarg). +uncompress(Data) -> + try iolist_size(Data) of + Size -> + if + Size >= 8 -> + Z = open(), + inflateInit(Z), + Bs = inflate(Z, Data), + inflateEnd(Z), + close(Z), + iolist_to_binary(Bs); + true -> + erlang:error(data_error) + end + catch + _:_ -> + erlang:error(badarg) + end. %% unzip/zip zlib without header (zip members) --spec zip(Binary) -> Compressed when - Binary :: binary(), +-spec zip(Data) -> Compressed when + Data :: iodata(), Compressed :: binary(). -zip(Binary) -> +zip(Data) -> Z = open(), deflateInit(Z, default, deflated, -?MAX_WBITS, 8, default), - Bs = deflate(Z, Binary, finish), + Bs = deflate(Z, Data, finish), deflateEnd(Z), close(Z), - list_to_binary(Bs). + iolist_to_binary(Bs). --spec unzip(Binary) -> Decompressed when - Binary :: binary(), +-spec unzip(Data) -> Decompressed when + Data :: iodata(), Decompressed :: binary(). -unzip(Binary) -> +unzip(Data) -> Z = open(), inflateInit(Z, -?MAX_WBITS), - Bs = inflate(Z, Binary), + Bs = inflate(Z, Data), inflateEnd(Z), close(Z), - list_to_binary(Bs). + iolist_to_binary(Bs). -spec gzip(Data) -> Compressed when Data :: iodata(), Compressed :: binary(). -gzip(Data) when is_binary(Data); is_list(Data) -> +gzip(Data) -> Z = open(), deflateInit(Z, default, deflated, 16+?MAX_WBITS, 8, default), Bs = deflate(Z, Data, finish), deflateEnd(Z), close(Z), - iolist_to_binary(Bs); -gzip(_) -> erlang:error(badarg). + iolist_to_binary(Bs). --spec gunzip(Binary) -> Decompressed when - Binary :: binary(), +-spec gunzip(Data) -> Decompressed when + Data :: iodata(), Decompressed :: binary(). -gunzip(Data) when is_binary(Data); is_list(Data) -> +gunzip(Data) -> Z = open(), inflateInit(Z, 16+?MAX_WBITS), Bs = inflate(Z, Data), inflateEnd(Z), close(Z), - iolist_to_binary(Bs); -gunzip(_) -> erlang:error(badarg). + iolist_to_binary(Bs). -spec collect(zstream()) -> iolist(). collect(Z) -> diff --git a/erts/test/erlc_SUITE.erl b/erts/test/erlc_SUITE.erl index 62e0e6813d..2b5cb11f02 100644 --- a/erts/test/erlc_SUITE.erl +++ b/erts/test/erlc_SUITE.erl @@ -213,13 +213,34 @@ deep_cwd_1(PrivDir) -> arg_overflow(Config) when is_list(Config) -> ?line {SrcDir, _OutDir, Cmd} = get_cmd(Config), ?line FileName = filename:join(SrcDir, "erl_test_ok.erl"), - ?line Args = lists:flatten([ ["-D", integer_to_list(N), "=1 "] || - N <- lists:seq(1,10000) ]), + %% Each -D option will be expanded to three arguments when + %% invoking 'erl'. + ?line NumDOptions = num_d_options(), + ?line Args = lists:flatten([ ["-D", integer_to_list(N, 36), "=1 "] || + N <- lists:seq(1, NumDOptions) ]), ?line run(Config, Cmd, FileName, Args, ["Warning: function foo/0 is unused\$", "_OK_"]), ok. +num_d_options() -> + case {os:type(),os:version()} of + {{win32,_},_} -> + %% The maximum size of a command line in the command + %% shell on Windows is 8191 characters. + %% Each -D option is expanded to "@dv NN 1", i.e. + %% 8 characters. (Numbers up to 1295 can be expressed + %% as two 36-base digits.) + 1000; + {{unix,linux},Version} when Version < {2,6,23} -> + %% On some older 64-bit versions of Linux, the maximum number + %% of arguments is 16383. + %% See: http://www.in-ulm.de/~mascheck/various/argmax/ + 5440; + {_,_} -> + 12000 + end. + erlc() -> case os:find_executable("erlc") of false -> |