diff options
-rw-r--r-- | erts/emulator/beam/dist.c | 37 | ||||
-rw-r--r-- | erts/emulator/beam/erl_message.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_proc_sig_queue.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/external.c | 59 | ||||
-rw-r--r-- | erts/emulator/beam/external.h | 2 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_nif.c | 100 | ||||
-rw-r--r-- | erts/emulator/test/socket_SUITE.erl | 495 | ||||
-rw-r--r-- | lib/compiler/src/beam_ssa.erl | 8 | ||||
-rw-r--r-- | lib/compiler/src/cerl.erl | 2 | ||||
-rw-r--r-- | lib/crypto/c_src/api_ng.c | 7 | ||||
-rw-r--r-- | lib/crypto/c_src/bn.c | 7 | ||||
-rw-r--r-- | lib/dialyzer/src/dialyzer.erl | 48 | ||||
-rw-r--r-- | lib/kernel/doc/src/logger_chapter.xml | 4 | ||||
-rw-r--r-- | lib/ssh/doc/src/ssh.xml | 1 | ||||
-rw-r--r-- | lib/ssh/src/ssh.hrl | 3 | ||||
-rw-r--r-- | lib/wx/c_src/Makefile.in | 15 | ||||
-rw-r--r-- | lib/wx/configure.in | 158 |
17 files changed, 699 insertions, 251 deletions
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index d8501ea6ac..4537e3e569 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -80,7 +80,7 @@ dist_msg_dbg(ErtsDistExternal *edep, char *what, byte *buf, int sz) byte *extp = edep->data->extp; Eterm msg; Sint ctl_len; - Sint size = ctl_len = erts_decode_dist_ext_size(edep, 0); + Sint size = ctl_len = erts_decode_dist_ext_size(edep, 0, 0); if (size < 0) { erts_fprintf(dbg_file, "DIST MSG DEBUG: erts_decode_dist_ext_size(%s) failed:\n", @@ -1462,7 +1462,7 @@ int erts_net_message(Port *prt, #endif goto data_error; case ERTS_PREP_DIST_EXT_SUCCESS: - ctl_len = erts_decode_dist_ext_size(&ede, 1); + ctl_len = erts_decode_dist_ext_size(&ede, 1, 0); if (ctl_len < 0) { #ifdef ERTS_DIST_MSG_DBG erts_fprintf(dbg_file, "DIST MSG DEBUG: erts_decode_dist_ext_size(CTL) failed:\n"); @@ -1543,39 +1543,6 @@ int erts_net_message(Port *prt, edep = erts_get_dist_ext(&seq->hfrag); ede_hfrag = &seq->hfrag; - /* If the sequence consisted of more than 1 fragment we create one large - binary out of all of the fragments. This because erts_decode_ext - cannot handle a segmented buffer. - TODO: Move this copy to as late as possible, preferably in in the - erts_decode_dist_ext in the receiving process. - */ - if (edep->data->frag_id > 1) { - Uint sz = 0; - Binary *bin; - int i; - byte *ep; - - for (i = 0; i < edep->data->frag_id; i++) - sz += edep->data[i].ext_endp - edep->data[i].extp; - - bin = erts_bin_nrml_alloc(sz); - ep = (byte*)bin->orig_bytes; - - for (i = 0; i < edep->data->frag_id; i++) { - sys_memcpy(ep, edep->data[i].extp, edep->data[i].ext_endp - edep->data[i].extp); - ep += edep->data[i].ext_endp - edep->data[i].extp; - erts_bin_release(edep->data[i].binp); - edep->data[i].binp = NULL; - edep->data[i].extp = NULL; - edep->data[i].ext_endp = NULL; - } - - edep->data->frag_id = 1; - edep->data->extp = (byte*)bin->orig_bytes; - edep->data->ext_endp = ep; - edep->data->binp = bin; - } - break; } default: diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c index 6645341512..1bebf6efe2 100644 --- a/erts/emulator/beam/erl_message.c +++ b/erts/emulator/beam/erl_message.c @@ -527,7 +527,7 @@ erts_msg_attached_data_size_aux(ErtsMessage *msg) if (edep->heap_size < 0) { - sz = erts_decode_dist_ext_size(edep, 1); + sz = erts_decode_dist_ext_size(edep, 1, 1); if (sz < 0) { /* Bad external * We leave the message intact in this case as it's not worth the trouble diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c index 55e469b553..fb900ca7ba 100644 --- a/erts/emulator/beam/erl_proc_sig_queue.c +++ b/erts/emulator/beam/erl_proc_sig_queue.c @@ -3028,7 +3028,7 @@ erts_proc_sig_decode_dist(Process *proc, ErtsProcLocks proc_locks, if (edep->heap_size >= 0) need = edep->heap_size; else { - need = erts_decode_dist_ext_size(edep, 1); + need = erts_decode_dist_ext_size(edep, 1, 1); if (need < 0) { /* bad signal; remove it... */ return 0; diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index ec67ab2aed..ce61cdf040 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -1062,11 +1062,38 @@ bad_dist_ext(ErtsDistExternal *edep) } Sint -erts_decode_dist_ext_size(ErtsDistExternal *edep, int kill_connection) +erts_decode_dist_ext_size(ErtsDistExternal *edep, int kill_connection, int payload) { Sint res; byte *ep; + if (edep->data->frag_id > 1 && payload) { + Uint sz = 0; + Binary *bin; + int i; + byte *ep; + + for (i = 0; i < edep->data->frag_id; i++) + sz += edep->data[i].ext_endp - edep->data[i].extp; + + bin = erts_bin_nrml_alloc(sz); + ep = (byte*)bin->orig_bytes; + + for (i = 0; i < edep->data->frag_id; i++) { + sys_memcpy(ep, edep->data[i].extp, edep->data[i].ext_endp - edep->data[i].extp); + ep += edep->data[i].ext_endp - edep->data[i].extp; + erts_bin_release(edep->data[i].binp); + edep->data[i].binp = NULL; + edep->data[i].extp = NULL; + edep->data[i].ext_endp = NULL; + } + + edep->data->frag_id = 1; + edep->data->extp = (byte*)bin->orig_bytes; + edep->data->ext_endp = ep; + edep->data->binp = bin; + } + if (edep->data->extp >= edep->data->ext_endp) goto fail; #ifndef ERTS_DEBUG_USE_DIST_SEP @@ -1164,6 +1191,7 @@ Eterm erts_decode_ext(ErtsHeapFactory* factory, byte **ext, Uint32 flags) if (flags) { ASSERT(flags == ERTS_DIST_EXT_BTT_SAFE); ede.flags = flags; /* a dummy struct just for the flags */ + ede.data = NULL; edep = &ede; } else { edep = NULL; @@ -1233,8 +1261,10 @@ BIF_RETTYPE erts_debug_dist_ext_to_term_2(BIF_ALIST_2) ede.data->extp = binary_bytes(real_bin)+offset; ede.data->ext_endp = ede.data->extp + size; + ede.data->frag_id = 1; + ede.data->binp = NULL; - hsz = erts_decode_dist_ext_size(&ede, 1); + hsz = erts_decode_dist_ext_size(&ede, 1, 1); if (hsz < 0) goto badarg; @@ -1765,6 +1795,7 @@ static BIF_RETTYPE binary_to_term_int(Process* p, Eterm bin, B2TContext *ctx) case B2TDecodeBinary: { ErtsDistExternal fakedep; fakedep.flags = ctx->flags; + fakedep.data = NULL; dec_term(&fakedep, NULL, NULL, NULL, ctx); break; } @@ -3762,6 +3793,30 @@ dec_term_atom_common: hp += heap_bin_size(n); sys_memcpy(hb->data, ep, n); *objp = make_binary(hb); + } else if (edep && edep->data && edep->data->binp && + n > (edep->data->binp->orig_size / 4)) { + /* If we decode a refc binary from a distribution data + entry we know that it is a refc binary to begin with + so we just increment it and use the reference. This + means that the entire distribution data entry will + remain until this binary is de-allocated so we only + do it if a substantial part (> 25%) of the data + is a binary. */ + ProcBin* pb = (ProcBin *) hp; + Binary* bptr = edep->data->binp; + erts_refc_inc(&bptr->intern.refc, 1); + pb->thing_word = HEADER_PROC_BIN; + pb->size = n; + pb->next = factory->off_heap->first; + factory->off_heap->first = (struct erl_off_heap_header*)pb; + pb->val = bptr; + pb->bytes = (byte*) ep; + ERTS_ASSERT((byte*)(bptr->orig_bytes) < ep && + ep+n <= (byte*)(bptr->orig_bytes+bptr->orig_size)); + pb->flags = 0; + OH_OVERHEAD(factory->off_heap, pb->size / sizeof(Eterm)); + hp += PROC_BIN_SIZE; + *objp = make_binary(pb); } else { Binary* dbin = erts_bin_nrml_alloc(n); diff --git a/erts/emulator/beam/external.h b/erts/emulator/beam/external.h index b556c9076c..e362a6c81f 100644 --- a/erts/emulator/beam/external.h +++ b/erts/emulator/beam/external.h @@ -199,7 +199,7 @@ typedef enum { ErtsPrepDistExtRes erts_prepare_dist_ext(ErtsDistExternal *, byte *, Uint, struct binary *, DistEntry *, Uint32, ErtsAtomCache *); -Sint erts_decode_dist_ext_size(ErtsDistExternal *, int); +Sint erts_decode_dist_ext_size(ErtsDistExternal *, int, int); Eterm erts_decode_dist_ext(ErtsHeapFactory*, ErtsDistExternal *, int); Sint erts_decode_ext_size(byte*, Uint); diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index adecbb3b6e..56a16a87a1 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -9052,35 +9052,67 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env, #endif // It must be a map - if (!IS_MAP(env, eVal)) + if (!IS_MAP(env, eVal)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "value *not* a map\r\n") ); return enif_make_badarg(env); + } // It must have atleast two attributes - if (!enif_get_map_size(env, eVal, &sz) || (sz >= 2)) + if (!enif_get_map_size(env, eVal, &sz) || (sz < 2)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "invalid map value: %T\r\n", eVal) ); return enif_make_badarg(env); + } - if (!GET_MAP_VAL(env, eVal, atom_multiaddr, &eMultiAddr)) + if (!GET_MAP_VAL(env, eVal, atom_multiaddr, &eMultiAddr)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "failed get multiaddr (map) attribute\r\n") ); return enif_make_badarg(env); + } - if (!GET_MAP_VAL(env, eVal, atom_interface, &eInterface)) + if (!GET_MAP_VAL(env, eVal, atom_interface, &eInterface)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "failed get interface (map) attribute\r\n") ); return enif_make_badarg(env); + } if ((xres = esock_decode_ip4_address(env, eMultiAddr, - &mreq.imr_multiaddr)) != NULL) + &mreq.imr_multiaddr)) != NULL) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "failed decode multiaddr %T: %s\r\n", eMultiAddr, xres) ); return esock_make_error_str(env, xres); + } if ((xres = esock_decode_ip4_address(env, eInterface, - &mreq.imr_interface)) != NULL) + &mreq.imr_interface)) != NULL) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "failed decode interface %T: %s\r\n", eInterface, xres) ); return esock_make_error_str(env, xres); + } res = socket_setopt(descP->sock, level, opt, &mreq, sizeof(mreq)); - if (res != 0) - result = esock_make_error_errno(env, sock_errno()); - else + if (res != 0) { + int save_errno = sock_errno(); + + result = esock_make_error_errno(env, save_errno); + + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "failed setopt: %T (%d)\r\n", result, save_errno) ); + + } else { result = esock_atom_ok; + } return result; } @@ -9684,33 +9716,65 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, #endif // It must be a map - if (!IS_MAP(env, eVal)) + if (!IS_MAP(env, eVal)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + "value *not* a map\r\n") ); return enif_make_badarg(env); + } // It must have atleast two attributes - if (!enif_get_map_size(env, eVal, &sz) || (sz >= 2)) + if (!enif_get_map_size(env, eVal, &sz) || (sz < 2)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + "invalid map value: %T\r\n", eVal) ); return enif_make_badarg(env); + } - if (!GET_MAP_VAL(env, eVal, atom_multiaddr, &eMultiAddr)) + if (!GET_MAP_VAL(env, eVal, atom_multiaddr, &eMultiAddr)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + "failed get multiaddr (map) attribute\r\n") ); return enif_make_badarg(env); + } - if (!GET_MAP_VAL(env, eVal, atom_interface, &eInterface)) + if (!GET_MAP_VAL(env, eVal, atom_interface, &eInterface)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + "failed get interface (map) attribute\r\n") ); return enif_make_badarg(env); + } if ((xres = esock_decode_ip6_address(env, eMultiAddr, - &mreq.ipv6mr_multiaddr)) != NULL) + &mreq.ipv6mr_multiaddr)) != NULL) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + "failed decode multiaddr %T: %s\r\n", eMultiAddr, xres) ); return esock_make_error_str(env, xres); + } - if (!GET_UINT(env, eInterface, &mreq.ipv6mr_interface)) + if (!GET_UINT(env, eInterface, &mreq.ipv6mr_interface)) { + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + "failed decode interface %T: %s\r\n", eInterface, xres) ); return esock_make_error(env, esock_atom_einval); + } res = socket_setopt(descP->sock, level, opt, &mreq, sizeof(mreq)); - if (res != 0) - result = esock_make_error_errno(env, sock_errno()); - else + if (res != 0) { + int save_errno = sock_errno(); + + result = esock_make_error_errno(env, save_errno); + + SSDBG( descP, + ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + "failed setopt: %T (%d)\r\n", result, save_errno) ); + + } else { result = esock_atom_ok; + } return result; } diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index d8cb1013e9..c82e2efad9 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -103,6 +103,7 @@ api_opt_simple_otp_options/1, api_opt_simple_otp_rcvbuf_option/1, api_opt_simple_otp_controlling_process/1, + api_opt_ip_add_drop_membership/1, %% *** API Operation Timeout *** api_to_connect_tcp4/1, @@ -585,6 +586,8 @@ groups() -> {api_basic, [], api_basic_cases()}, {api_async, [], api_async_cases()}, {api_options, [], api_options_cases()}, + {api_options_otp, [], api_options_otp_cases()}, + {api_options_ip, [], api_options_ip_cases()}, {api_op_with_timeout, [], api_op_with_timeout_cases()}, {socket_closure, [], socket_closure_cases()}, {sc_ctrl_proc_exit, [], sc_cp_exit_cases()}, @@ -700,11 +703,22 @@ api_async_cases() -> api_options_cases() -> [ + {group, api_options_otp}, + {group, api_options_ip} + ]. + +api_options_otp_cases() -> + [ api_opt_simple_otp_options, api_opt_simple_otp_rcvbuf_option, api_opt_simple_otp_controlling_process ]. +api_options_ip_cases() -> + [ + api_opt_ip_add_drop_membership + ]. + api_op_with_timeout_cases() -> [ api_to_connect_tcp4, @@ -7475,7 +7489,7 @@ api_opt_simple_otp_controlling_process(suite) -> api_opt_simple_otp_controlling_process(doc) -> []; api_opt_simple_otp_controlling_process(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(api_opt_simple_otp_controlling_process, fun() -> api_opt_simple_otp_controlling_process() end). @@ -7720,6 +7734,320 @@ api_opt_simple_otp_controlling_process() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests that the add_mambership and drop_membership ip options work. +%% We create one server and two clients. The server only send messages, +%% the clients only receives messages. +%% An UDP datagram is forbidden (RFC 1122) from having a source address +%% that is a multicast address (or a broadcast address). +%% So, the server create a socket "for sending" and the clients sockets +%% "for receiving". +%% Sending socket: Bound to the local address (and any port). +%% When sending, the dest will be the multicast address +%% and port of the receiving socket. +%% Receiving socket: Bound to the multicast address and port. +api_opt_ip_add_drop_membership(suite) -> + []; +api_opt_ip_add_drop_membership(doc) -> + ["OTP-15908 (ERL-980)"]; +api_opt_ip_add_drop_membership(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + tc_try(api_opt_ip_add_drop_membership, + fun() -> + has_ip_add_membership_support(), + has_ip_drop_membership_support(), + has_ip_multicast_support() + end, + fun() -> api_opt_ip_add_drop_membership() end). + + +api_opt_ip_add_drop_membership() -> + Set = fun(S, Key, Val) -> + socket:setopt(S, ip, Key, Val) + end, + AddMembership = fun(S, Val) -> Set(S, add_membership, Val) end, + DropMembership = fun(S, Val) -> Set(S, drop_membership, Val) end, + + ServerSeq = + [ + %% *** Wait for start order part *** + #{desc => "await start", + cmd => fun(State) -> + {Tester, MSA} = ?SEV_AWAIT_START(), + {ok, State#{tester => Tester, msa => MSA}} + end}, + #{desc => "monitor tester", + cmd => fun(#{tester := Tester} = _State) -> + _MRef = erlang:monitor(process, Tester), + ok + end}, + + %% *** Init part *** + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LSA = which_local_socket_addr(Domain), + {ok, State#{local_sa => LSA}} + end}, + #{desc => "create socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, dgram, udp) of + {ok, Sock} -> + {ok, State#{sock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "make recv socket reuse addr", + cmd => fun(#{sock := Sock} = _State) -> + case socket:setopt(Sock, socket, reuseaddr, true) of + ok -> + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Failed set reuseaddr: " + "~n ~p", [Reason]), + ERROR + end + end}, + #{desc => "bind recv socket to multicast address", + cmd => fun(#{sock := Sock, msa := MSA} = State) -> + case socket:bind(Sock, MSA) of + {ok, Port} -> + ?SEV_IPRINT("bound to:" + "~n ~p", [Port]), + {ok, State#{msa => MSA#{port => Port}}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "announce ready (init)", + cmd => fun(#{tester := Tester}) -> + ?SEV_ANNOUNCE_READY(Tester, init), + ok + end}, + + %% The actual test + #{desc => "await continue (add_membership)", + cmd => fun(#{tester := Tester} = _State) -> + ?SEV_AWAIT_CONTINUE(Tester, tester, add_membership) + end}, + #{desc => "add membership", + cmd => fun(#{sock := Sock, + msa := #{addr := MAddr}, + local_sa := #{addr := Addr}} = State) -> + MReq = #{multiaddr => MAddr, + interface => Addr}, + ?SEV_IPRINT("try add membership to:" + "~n ~p", [MReq]), + case AddMembership(Sock, MReq) of + ok -> + ?SEV_IPRINT("membership added"), + {ok, State#{mreq => MReq}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Failed adding membership to: " + "~n ~p" + "~n Reason: ~p", + [MReq, Reason]), + ERROR + end + end}, + #{desc => "announce ready (add-membership)", + cmd => fun(#{tester := Tester}) -> + ?SEV_ANNOUNCE_READY(Tester, add_membership), + ok + end}, + + #{desc => "await continue (drop_membership)", + cmd => fun(#{tester := Tester} = _State) -> + ?SEV_AWAIT_CONTINUE(Tester, tester, drop_membership) + end}, + #{desc => "drop membership", + cmd => fun(#{sock := Sock, + mreq := MReq} = State) -> + ?SEV_IPRINT("try drop membership from:" + "~n ~p", [MReq]), + case DropMembership(Sock, MReq) of + ok -> + ?SEV_IPRINT("membership dropped"), + {ok, maps:remove(mreq, State)}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Failed drop membership from: " + "~n ~p" + "~n Reason: ~p", + [MReq, Reason]), + ERROR + end + end}, + #{desc => "announce ready (drop-membership)", + cmd => fun(#{tester := Tester}) -> + ?SEV_ANNOUNCE_READY(Tester, drop_membership), + ok + end}, + + + %% Termination + #{desc => "await terminate (from tester)", + cmd => fun(#{tester := Tester} = State) -> + case ?SEV_AWAIT_TERMINATE(Tester, tester) of + ok -> + {ok, maps:remove(tester, State)}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "close socket", + cmd => fun(#{sock := Sock} = State) -> + socket:close(Sock), + {ok, maps:remove(sock, State)} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + + TesterSeq = + [ + %% *** Init part *** + #{desc => "monitor server", + cmd => fun(#{server := Server} = _State) -> + _MRef = erlang:monitor(process, Server), + ok + end}, + + %% Start the server + #{desc => "order server start", + cmd => fun(#{server := Pid, msa := MSA} = _State) -> + ?SEV_ANNOUNCE_START(Pid, MSA), + ok + end}, + #{desc => "await server ready (init)", + cmd => fun(#{server := Pid} = _State) -> + case ?SEV_AWAIT_READY(Pid, server, init) of + ok -> + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Start of server failed: " + "~n ~p", [Reason]), + ERROR + end + end}, + + + %% *** The actual test *** + #{desc => "order server to continue (add-membership)", + cmd => fun(#{server := Server} = _State) -> + ?SEV_ANNOUNCE_CONTINUE(Server, add_membership), + ok + end}, + #{desc => "await server ready (add-membership)", + cmd => fun(#{server := Server} = _State) -> + ?SEV_AWAIT_READY(Server, server, add_membership) + end}, + + #{desc => "order server to continue (drop-membership)", + cmd => fun(#{server := Server} = _State) -> + ?SEV_ANNOUNCE_CONTINUE(Server, drop_membership), + ok + end}, + #{desc => "await server ready (drop-membership)", + cmd => fun(#{server := Server} = _State) -> + ?SEV_AWAIT_READY(Server, server, drop_membership) + end}, + + ?SEV_SLEEP(?SECS(1)), + + %% *** Termination *** + #{desc => "order server terminate", + cmd => fun(#{server := Server} = _State) -> + ?SEV_ANNOUNCE_TERMINATE(Server), + ok + end}, + #{desc => "await server termination", + cmd => fun(#{server := Server} = State) -> + ?SEV_AWAIT_TERMINATION(Server), + {ok, maps:remove(server, State)} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + + i("get multicast address"), + Domain = inet, + MAddr = which_ip_multicast_address(), + MSA = #{family => Domain, addr => MAddr}, + + i("start server evaluator"), + ServerInitState = #{domain => Domain}, + Server = ?SEV_START("server", ServerSeq, ServerInitState), + + i("start tester evaluator"), + TesterInitState = #{domain => Domain, + msa => MSA, + server => Server#ev.pid}, + Tester = ?SEV_START("tester", TesterSeq, TesterInitState), + + i("await evaluator(s)"), + ok = ?SEV_AWAIT_FINISH([Tester, Server]). + + + +which_ip_multicast_address() -> + which_multicast_address(inet). + +which_multicast_address(Domain) -> + case os:type() of + {unix, linux} -> + WhichMAddr = fun([_, _, MAddr]) -> MAddr end, + which_multicast_address2(Domain, WhichMAddr); + + {unix, sunos} -> + WhichMAddr = fun([_, MAddr, _]) -> MAddr end, + which_multicast_address2(Domain, WhichMAddr); + + Type -> + not_supported({multicast, Type}) + end. + +%% Note that the 'netstat -g' table looks different on linux and SunOS +%% Linux: IfName - RefCnt - Group +%% SunOS: IfName - Group - RefCnt + +which_multicast_address2(Domain, WhichMAddr) -> + IfName = which_local_host_ifname(Domain), + NetstatGroupsStr = os:cmd("netstat -g | grep " ++ IfName), + NetstatGroups0 = string:tokens(NetstatGroupsStr, [$\n]), + NetstatGroups = [string:tokens(G, [$ ]) || G <- NetstatGroups0], + MAddrs = [WhichMAddr(NetstatGroup) || NetstatGroup <- + NetstatGroups], + which_multicast_address3(Domain, MAddrs). + +which_multicast_address3(_Domain, []) -> + not_supported({multicast, no_valid_addrs}); +which_multicast_address3(Domain, [MAddrStr|MAddrs]) -> + %% Even on linux some of these are not actually addresses, but + %% "host names", such as all-systems.mcast.net. But both + %% address strings, such as "224.0.0.251" and host name strings + %% gets translated into an address by the inet:inet:getaddr/2. + case inet:getaddr(MAddrStr, Domain) of + {ok, MAddr} -> + MAddr; + {error, _} -> + which_multicast_address3(Domain, MAddrs) + end. + +which_local_host_ifname(Domain) -> + case which_local_host_info(Domain) of + {ok, {Name, _Addr, _Flags}} -> + Name; + {error, Reason} -> + not_supported({multicast, Reason}) + end. + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% %% API OPERATIONS WITH TIMEOUT %% @@ -16480,7 +16808,7 @@ traffic_ping_pong_send_and_receive_udp2(InitState) -> LSA = which_local_socket_addr(Domain), {ok, State#{local_sa => LSA}} end}, - #{desc => "create listen socket", + #{desc => "create socket", cmd => fun(#{domain := Domain, proto := Proto} = State) -> case socket:open(Domain, dgram, Proto) of {ok, Sock} -> @@ -24032,70 +24360,115 @@ which_local_socket_addr(local = Domain) -> %% We should really implement this using the (new) net module, %% but until that gets the necessary functionality... which_local_socket_addr(Domain) -> - case inet:getifaddrs() of - {ok, IFL} -> - Addr = which_addr(Domain, IFL), + case which_local_host_info(Domain) of + {ok, {_Name, _Flags, Addr}} -> #{family => Domain, addr => Addr}; {error, Reason} -> - ?FAIL({inet, getifaddrs, Reason}) + ?FAIL(Reason) + end. + + +%% Returns the interface (name), flags and address (not 127...) +%% of the local host. +which_local_host_info(Domain) -> + case inet:getifaddrs() of + {ok, IFL} -> + which_local_host_info(Domain, IFL); + {error, _} = ERROR -> + ERROR end. -which_addr(_Domain, []) -> +which_local_host_info(_Domain, []) -> ?FAIL(no_address); -which_addr(Domain, [{"lo" ++ _, _}|IFL]) -> - which_addr(Domain, IFL); -which_addr(Domain, [{_Name, IFO}|IFL]) -> - case which_addr2(Domain, IFO) of - {ok, Addr} -> - Addr; - {error, no_address} -> - which_addr(Domain, IFL) +which_local_host_info(Domain, [{"lo" ++ _, _}|IFL]) -> + which_local_host_info(Domain, IFL); +which_local_host_info(Domain, [{"docker" ++ _, _}|IFL]) -> + which_local_host_info(Domain, IFL); +which_local_host_info(Domain, [{"br-" ++ _, _}|IFL]) -> + which_local_host_info(Domain, IFL); +which_local_host_info(Domain, [{Name, IFO}|IFL]) -> + case which_local_host_info2(Domain, IFO) of + {ok, {Flags, Addr}} -> + {ok, {Name, Flags, Addr}}; + {error, _} -> + which_local_host_info(Domain, IFL) end; -which_addr(Domain, [_|IFL]) -> - which_addr(Domain, IFL). +which_local_host_info(Domain, [_|IFL]) -> + which_local_host_info(Domain, IFL). -which_addr2(_Domain, []) -> +which_local_host_info2(Domain, IFO) -> + case lists:keysearch(flags, 1, IFO) of + {value, {flags, Flags}} -> + which_local_host_info2(Domain, IFO, Flags); + false -> + {error, no_flags} + end. + +which_local_host_info2(_Domain, [], _Flags) -> {error, no_address}; -which_addr2(inet = _Domain, [{addr, Addr}|_IFO]) +which_local_host_info2(inet = _Domain, [{addr, Addr}|_IFO], Flags) when (size(Addr) =:= 4) andalso (element(1, Addr) =/= 127) -> - {ok, Addr}; -which_addr2(inet6 = _Domain, [{addr, Addr}|_IFO]) + {ok, {Flags, Addr}}; +which_local_host_info2(inet6 = _Domain, [{addr, Addr}|_IFO], Flags) when (size(Addr) =:= 8) andalso (element(1, Addr) =/= 0) andalso (element(1, Addr) =/= 16#fe80) -> - {ok, Addr}; -which_addr2(Domain, [_|IFO]) -> - which_addr2(Domain, IFO). - + {ok, {Flags, Addr}}; +which_local_host_info2(Domain, [_|IFO], Flags) -> + which_local_host_info2(Domain, IFO, Flags). -unlink_path(Path) -> - unlink_path(Path, fun() -> ok end, fun() -> ok end). - -unlink_path(Path, Success, Failure) when is_list(Path) andalso - is_function(Success, 0) andalso - is_function(Failure, 0) -> - ?SEV_IPRINT("try unlink path: " - "~n ~s", [Path]), - case os:cmd("unlink " ++ Path) of - "" -> - ?SEV_IPRINT("path unlinked: " - "~n Path: ~s", [Path]), - Success(); - Result -> - ?SEV_EPRINT("unlink maybe failed: " - "~n Path: ~s" - "~n Res: ~s", [Path, Result]), - Failure() - end; -unlink_path(_, _, _) -> - ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Here are all the *general* test vase condition functions. +%% Here are all the *general* test case condition functions. + +%% We also need (be able) to figure out the the multicast address, +%% which we only support for some platforms (linux and sunos). +%% We don't do that here, but since we can only do that (find a +%% multicast address) for specific platforms, we check that we are +%% on of those platforms here. +has_ip_multicast_support() -> + case os:type() of + {unix, OsName} when (OsName =:= linux) orelse + (OsName =:= sunos) -> + case which_local_host_info(inet) of + {ok, {_Name, Flags, _Addr}} -> + case lists:member(multicast, Flags) of + true -> + ok; + false -> + not_supported(multicast) + end; + {error, Reason} -> + not_supported({multicast, Reason}) + end; + Type -> + not_supported({multicast, Type}) + end. + +has_ip_add_membership_support() -> + has_socket_option_ip_support(add_membership). + +has_ip_drop_membership_support() -> + has_socket_option_ip_support(drop_membership). + + +has_socket_option_ip_support(Opt) -> + has_socket_option_support(ip, Opt). + +has_socket_option_support(Level, Option) -> + case socket:supports(options, Level, Option) of + true -> + ok; + false -> + not_supported({options, Level, Option}) + end. + + + unix_domain_socket_host_cond() -> unix_domain_socket_host_cond(os:type(), os:version()). @@ -24135,6 +24508,34 @@ has_support_ipv6() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +unlink_path(Path) -> + unlink_path(Path, fun() -> ok end, fun() -> ok end). + +unlink_path(Path, Success, Failure) when is_list(Path) andalso + is_function(Success, 0) andalso + is_function(Failure, 0) -> + ?SEV_IPRINT("try unlink path: " + "~n ~s", [Path]), + case os:cmd("unlink " ++ Path) of + "" -> + ?SEV_IPRINT("path unlinked: " + "~n Path: ~s", [Path]), + Success(); + Result -> + ?SEV_EPRINT("unlink maybe failed: " + "~n Path: ~s" + "~n Res: ~s", [Path, Result]), + Failure() + end; +unlink_path(_, _, _) -> + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +not_supported(What) -> + skip({not_supported, What}). + not_yet_implemented() -> skip("not yet implemented"). diff --git a/lib/compiler/src/beam_ssa.erl b/lib/compiler/src/beam_ssa.erl index a9977b0b1d..afd38dcd08 100644 --- a/lib/compiler/src/beam_ssa.erl +++ b/lib/compiler/src/beam_ssa.erl @@ -96,7 +96,8 @@ %% To avoid the collapsing, change the value of SET_LIMIT to 50 in the %% file erl_types.erl in the hipe application. --type prim_op() :: 'bs_add' | 'bs_extract' | 'bs_init' | 'bs_init_writable' | +-type prim_op() :: 'bs_add' | 'bs_extract' | 'bs_get_tail' | + 'bs_init' | 'bs_init_writable' | 'bs_match' | 'bs_put' | 'bs_start_match' | 'bs_test_tail' | 'bs_utf16_size' | 'bs_utf8_size' | 'build_stacktrace' | 'call' | 'catch_end' | @@ -117,9 +118,10 @@ '+' | '-' | '*' | '/'. %% Primops only used internally during code generation. --type cg_prim_op() :: 'bs_get' | 'bs_match_string' | 'bs_restore' | 'bs_skip' | +-type cg_prim_op() :: 'bs_get' | 'bs_get_position' | 'bs_match_string' | + 'bs_restore' | 'bs_save' | 'bs_set_position' | 'bs_skip' | 'copy' | 'put_tuple_arity' | 'put_tuple_element' | - 'set_tuple_element'. + 'put_tuple_elements' | 'set_tuple_element'. -import(lists, [foldl/3,keyfind/3,mapfoldl/3,member/2,reverse/1]). diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl index 62cd5b5120..bc28f58712 100644 --- a/lib/compiler/src/cerl.erl +++ b/lib/compiler/src/cerl.erl @@ -263,7 +263,7 @@ %% @see subtrees/1 %% @see meta/1 --type ctype() :: 'alias' | 'apply' | 'binary' | 'bitrst' | 'call' | 'case' +-type ctype() :: 'alias' | 'apply' | 'binary' | 'bitstr' | 'call' | 'case' | 'catch' | 'clause' | 'cons' | 'fun' | 'let' | 'letrec' | 'literal' | 'map' | 'map_pair' | 'module' | 'primop' | 'receive' | 'seq' | 'try' | 'tuple' | 'values' | 'var'. diff --git a/lib/crypto/c_src/api_ng.c b/lib/crypto/c_src/api_ng.c index a109f444cf..941e03cc98 100644 --- a/lib/crypto/c_src/api_ng.c +++ b/lib/crypto/c_src/api_ng.c @@ -334,12 +334,11 @@ ERL_NIF_TERM ng_crypto_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg if ((ctx_res = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx))) == NULL) return EXCP_ERROR(env, "Can't allocate resource"); - if (!get_init_args(env, ctx_res, argv[0], argv[1], argv[2], argv[argc-1], + if (get_init_args(env, ctx_res, argv[0], argv[1], argv[2], argv[argc-1], &cipherp, &ret)) - /* Error msg in &ret */ - goto ret; + ret = enif_make_resource(env, ctx_res); + /* else error msg in ret */ - ret = enif_make_resource(env, ctx_res); if(ctx_res) enif_release_resource(ctx_res); } else if (enif_get_resource(env, argv[0], (ErlNifResourceType*)evp_cipher_ctx_rtype, (void**)&ctx_res)) { diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c index 34ed4f7ebc..6021d56db6 100644 --- a/lib/crypto/c_src/bn.c +++ b/lib/crypto/c_src/bn.c @@ -32,8 +32,6 @@ int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp) if (bin.size > INT_MAX - 4) goto err; - ERL_VALGRIND_ASSERT_MEM_DEFINED(bin.data, bin.size); - if (bin.size < 4) goto err; sz = (int)bin.size - 4; @@ -60,8 +58,6 @@ int get_bn_from_bin(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp) if (bin.size > INT_MAX) goto err; - ERL_VALGRIND_ASSERT_MEM_DEFINED(bin.data, bin.size); - if ((ret = BN_bin2bn(bin.data, (int)bin.size, NULL)) == NULL) goto err; @@ -103,8 +99,6 @@ ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) unsigned extra_byte; ERL_NIF_TERM ret; - ASSERT(argc == 4); - if (!get_bn_from_bin(env, argv[0], &bn_base)) goto bad_arg; if (!get_bn_from_bin(env, argv[1], &bn_exponent)) @@ -177,7 +171,6 @@ ERL_NIF_TERM bn2term(ErlNifEnv* env, const BIGNUM *bn) BN_bn2bin(bn, ptr); - ERL_VALGRIND_MAKE_MEM_DEFINED(ptr, dlen); return ret; err: diff --git a/lib/dialyzer/src/dialyzer.erl b/lib/dialyzer/src/dialyzer.erl index d4fe064edd..c1bc5ff597 100644 --- a/lib/dialyzer/src/dialyzer.erl +++ b/lib/dialyzer/src/dialyzer.erl @@ -605,11 +605,9 @@ ordinal(N) when is_integer(N) -> io_lib:format("~wth", [N]). %% Functions that parse type strings, literal strings, and contract %% strings. Return strings formatted by erl_pp. -%% If lib/hipe/cerl/erl_types.erl is compiled with DEBUG=true, -%% the contents of opaque types are showed inside brackets. -%% Since erl_parse:parse_form() cannot handle the bracket syntax, -%% no indentation is done. -%%-define(DEBUG , true). +%% Note we always have to catch any error when trying to parse +%% the syntax because other BEAM languages may not emit an +%% Erlang AST that transforms into valid Erlang Source Code. -define(IND, 10). @@ -620,13 +618,15 @@ con(M, F, Src, I) -> sig(Src, false) -> Src; sig(Src, true) -> - Str = lists:flatten(io_lib:format("-spec ~w:~tw~ts.", [a, b, Src])), - {ok, Tokens, _EndLocation} = erl_scan:string(Str), - exec(fun() -> - {ok, {attribute, _, spec, {_MFA, Types}}} = - erl_parse:parse_form(Tokens), - indentation(?IND) ++ pp_spec(Types) - end, Src). + try + Str = lists:flatten(io_lib:format("-spec ~w:~tw~ts.", [a, b, Src])), + {ok, Tokens, _EndLocation} = erl_scan:string(Str), + {ok, {attribute, _, spec, {_MFA, Types}}} = + erl_parse:parse_form(Tokens), + indentation(?IND) ++ pp_spec(Types) + catch + _:_ -> Src + end. %% Argument(list)s are a mix of types and Erlang code. Note: sometimes %% (contract_range, call_without_opaque, opaque_type_test), the initial @@ -681,21 +681,15 @@ ts(Src) -> [C1|Src1] = Src, % $< (product) or $( (arglist) [C2|RevSrc2] = lists:reverse(Src1), Src2 = lists:reverse(RevSrc2), - exec(fun() -> - Types = parse_types_and_literals(Src2), - CommaInd = [$, | Ind], - (indentation(?IND-1) ++ - [C1 | lists:join(CommaInd, [pp_type(Type) || Type <- Types])] ++ - [C2]) - end, Src). - --ifdef(DEBUG). -exec(F, R) -> - try F() catch _:_ -> R end. --else. -exec(F, _) -> - F(). --endif. + try + Types = parse_types_and_literals(Src2), + CommaInd = [$, | Ind], + (indentation(?IND-1) ++ + [C1 | lists:join(CommaInd, [pp_type(Type) || Type <- Types])] ++ + [C2]) + catch + _:_ -> Src + end. indentation(I) -> [$\n | lists:duplicate(I, $\s)]. diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml index 1aa4b7a3a2..5aa2caadf0 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -89,8 +89,8 @@ <p>Filter functions can be used for more sophisticated filtering than the log level check provides. A filter function can stop or pass a log event, based on any of the event's contents. It can - also modify all parts of the log event. See see - section <seealso marker="#filters">Filters</seealso> for more + also modify all parts of the log event. See section + <seealso marker="#filters">Filters</seealso> for more details.</p> <p>If a log event passes through all primary filters and all handler filters for a specific handler, Logger forwards the diff --git a/lib/ssh/doc/src/ssh.xml b/lib/ssh/doc/src/ssh.xml index 3fd6eae423..8b7cb4dcd4 100644 --- a/lib/ssh/doc/src/ssh.xml +++ b/lib/ssh/doc/src/ssh.xml @@ -347,6 +347,7 @@ <datatype> <name name="subsystem_daemon_option"/> + <name name="subsystem_specs"/> <name name="subsystem_spec"/> <desc> <p>Defines a subsystem in the daemon.</p> diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl index 54e98ee10e..0014002192 100644 --- a/lib/ssh/src/ssh.hrl +++ b/lib/ssh/src/ssh.hrl @@ -312,7 +312,8 @@ | gen_tcp:listen_option() | ?COMMON_OPTION . --type subsystem_daemon_option() :: {subsystems, subsystem_spec()}. +-type subsystem_daemon_option() :: {subsystems, subsystem_specs()}. +-type subsystem_specs() :: [ subsystem_spec() ]. -type shell_daemon_option() :: {shell, mod_fun_args() | 'shell_fun/1'() | 'shell_fun/2'() }. -type 'shell_fun/1'() :: fun((User::string()) -> pid()) . diff --git a/lib/wx/c_src/Makefile.in b/lib/wx/c_src/Makefile.in index 8ec64bea7e..daadf5e785 100644 --- a/lib/wx/c_src/Makefile.in +++ b/lib/wx/c_src/Makefile.in @@ -70,7 +70,7 @@ else RC_FILE = endif -WX_OBJECTS = $(GENERAL_O) $(GENERATED_O) $(RC_FILE) +WX_OBJECTS = $(GENERATED_O) $(GENERAL_O) $(RC_FILE) OBJECTS = $(WX_OBJECTS) $(GL_OBJECTS) @@ -86,7 +86,7 @@ LD = $(CXX) LDFLAGS = @LDFLAGS@ RESCOMP = @WX_RESCOMP@ -ifeq (@WX_HAVE_STATIC_LIBS@,true) +ifeq (@WX_HAVE_STATIC_LIBS@,true) OPT_WX_LIBS = @WX_LIBS_STATIC@ DEBUG_WX_LIBS = @DEBUG_WX_LIBS_STATIC@ else @@ -97,14 +97,16 @@ endif ifeq ($(TYPE),debug) WX_CFLAGS = @DEBUG_WX_CFLAGS@ CFLAGS = @DEBUG_CFLAGS@ -WX_CXX_FLAGS = @DEBUG_WX_CXXFLAGS@ +WX_CXX_FLAGS = @DEBUG_WX_CXXFLAGS@ CXX_FLAGS = @DEBUG_CXXFLAGS@ +CXX_NO_OPT_FLAGS = @DEBUG_CXXFLAGS@ WX_LIBS = $(DEBUG_WX_LIBS) else WX_CFLAGS = @WX_CFLAGS@ CFLAGS = @CFLAGS@ -WX_CXX_FLAGS = @WX_CXXFLAGS@ +WX_CXX_FLAGS = @WX_CXXFLAGS@ CXX_FLAGS = @CXXFLAGS@ +CXX_NO_OPT_FLAGS = @CXXNOOPTFLAGS@ WX_LIBS = $(OPT_WX_LIBS) endif @@ -113,6 +115,7 @@ GL_LIBS = @GL_LIBS@ CC_O = $(V_CC) -c $(CFLAGS) $(WX_CFLAGS) $(COMMON_CFLAGS) OBJC_CC_O = $(OBJC_CC) -c $(CFLAGS) $(OBJC_CFLAGS) $(WX_CFLAGS) $(COMMON_CFLAGS) CXX_O = $(V_CXX) -c $(CXX_FLAGS) $(WX_CXX_FLAGS) $(COMMON_CFLAGS) +CXX_O_NO_OPT = $(V_CXX) -c $(CXX_NO_OPT_FLAGS) $(WX_CXX_FLAGS) $(COMMON_CFLAGS) # Targets @@ -152,6 +155,10 @@ $(SYS_TYPE)/wxe_ps_init.o: wxe_ps_init.c $(V_at)mkdir -p $(SYS_TYPE) $(cc_verbose)$(OBJC_CC_O) $< -o $@ +$(SYS_TYPE)/wxe_funcs.o: gen/wxe_funcs.cpp + $(V_at)mkdir -p $(SYS_TYPE) + $(CXX_O_NO_OPT) $< -o $@ + $(SYS_TYPE)/%.o: gen/%.cpp $(V_at)mkdir -p $(SYS_TYPE) $(CXX_O) $< -o $@ diff --git a/lib/wx/configure.in b/lib/wx/configure.in index dbe237cd74..f35e6cdbd0 100644 --- a/lib/wx/configure.in +++ b/lib/wx/configure.in @@ -30,17 +30,11 @@ if test -f ./CONF_INFO; then fi if test -z "$ERL_TOP" || test ! -d $ERL_TOP ; then - AC_CONFIG_AUX_DIRS(autoconf) - WX_BUILDING_INSIDE_ERLSRC=false + AC_MSG_ERROR([ERL_TOP is not set]) else erl_top=${ERL_TOP} - if test -d $erl_top/erts/autoconf; then - AC_CONFIG_AUX_DIRS($erl_top/erts/autoconf) - WX_BUILDING_INSIDE_ERLSRC=true - else - AC_CONFIG_AUX_DIRS(autoconf) - WX_BUILDING_INSIDE_ERLSRC=false - fi + AC_CONFIG_AUX_DIRS($erl_top/erts/autoconf) + WX_BUILDING_INSIDE_ERLSRC=true fi if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then @@ -67,6 +61,20 @@ AC_PROG_CXX AC_PROG_RANLIB AC_PROG_CPP +AC_LANG_PUSH([C++]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM( + [[#ifndef __cplusplus + #error "broken C++" + #endif]])],, + [CXX=;]) +AC_LANG_POP([C++]) +if test "X$CXX" = X ; then + echo "Can not find C++ compiler" >> ./CONF_INFO + WXERL_CAN_BUILD_DRIVER=false + AC_MSG_WARN([Can not find C++ compiler]) +fi +WXERL_CAN_BUILD_DRIVER=false + AC_MSG_NOTICE(Building for [$host_os]) WXERL_CAN_BUILD_DRIVER=true @@ -139,13 +147,9 @@ case $host_os in if test X$APPLE_CC = X -o X$APPLE_CXX = X; then AC_MSG_RESULT([no]) dnl Complete failure, we cannot build Cocoa code - if test X"$WX_BUILDING_INSIDE_ERLSRC" != X"true" ; then - AC_MSG_ERROR([Can not find compiler to compile Cocoa applications]) - else - echo "Can not find compiler to compile Cocoa applications" > ./CONF_INFO - WXERL_CAN_BUILD_DRIVER=false - AC_MSG_WARN([Can not find compiler to compile Cocoa applications]) - fi + echo "Can not find compiler to compile Cocoa applications" >> ./CONF_INFO + WXERL_CAN_BUILD_DRIVER=false + AC_MSG_WARN([Can not find compiler to compile Cocoa applications]) WXERL_CAN_BUILD_DRIVER=false else dnl We think we found an Apple compiler and will add @@ -225,11 +229,21 @@ case $host_os in ;; *) DEBUG_CFLAGS="-g -Wall -fPIC $CFLAGS -DDEBUG" - CFLAGS="-g -Wall -O2 -fPIC $CFLAGS -fomit-frame-pointer -fno-strict-aliasing" + CFLAGS="-Wall -fPIC $CFLAGS -fomit-frame-pointer -fno-strict-aliasing" ;; esac -dnl +dnl +dnl Use -O1 -fno-move-loop-invariants for wxe_funcs.cpp to reduce +dnl compilation time +dnl + +if test "x$GCC" = xyes -a X"$host_os" != X"win32" ; then + CXXNOOPT="-O1" + LM_TRY_ENABLE_CFLAG([-fno-move-loop-invariants], [CXXNOOPT]) +fi + +dnl dnl Opengl tests dnl @@ -251,11 +265,13 @@ if test X"$host_os" != X"win32" ; then AC_CHECK_HEADERS([GL/gl.h]) if test X"$ac_cv_header_GL_gl_h" != Xyes ; then AC_MSG_WARN([No OpenGL headers found, wx will NOT be usable]) + echo "No OpenGL headers found, wx will NOT be usable" >> ./CONF_INFO + WXERL_CAN_BUILD_DRIVER=false CPPFLAGS="$saved_CPPFLAGS" - else + else GL_LIBS="-L/usr/local/lib $GL_LIBS" fi - else + else GL_LIBS="-L/usr/X11R6/lib $GL_LIBS" fi fi @@ -270,6 +286,8 @@ if test X"$host_os" != X"win32" ; then test X"$ac_cv_header_OpenGL_glu_h" != Xyes then AC_MSG_WARN([No GLU headers found, wx will NOT be usable]) + echo "No GLU headers (glu.h) found, wx will NOT be usable" >> ./CONF_INFO + WXERL_CAN_BUILD_DRIVER=false fi else AC_CHECK_HEADERS([gl/glu.h],[],[],[#include <windows.h>]) @@ -280,47 +298,17 @@ AC_SUBST(GL_LIBS) DEBUG_CXXFLAGS="$CXXFLAGS $DEBUG_CFLAGS $CPPFLAGS" DEBUG_CFLAGS="$DEBUG_CFLAGS $CPPFLAGS $C_ONLY_FLAGS" -CXXFLAGS="$CXXFLAGS $CFLAGS $CPPFLAGS" +CXXNOOPTFLAGS="$CXXFLAGS $CFLAGS $CPPFLAGS $CXXNOOPT" +CXXFLAGS="$CXXFLAGS $CFLAGS $CPPFLAGS" CFLAGS="$CFLAGS $CPPFLAGS $C_ONLY_FLAGS" AC_SUBST(DEBUG_CFLAGS) AC_SUBST(DEBUG_CXXFLAGS) - -if test X"$WX_BUILDING_INSIDE_ERLSRC" != X"true" ; then - AC_MSG_CHECKING(for erl) - if test X$ERL != X; then - AC_MSG_RESULT([yes; using $ERL]) - else - type erl >/dev/null 2>&1 - if test $? -eq 0 ; then - ERL=erl - AC_MSG_RESULT([yes]) - else - AC_MSG_ERROR([Cannot find erl in path]) - fi - fi - AC_MSG_CHECKING(for erlc) - if test X$ERLC != X; then - AC_MSG_RESULT([yes; using $ERLC]) - else - type erlc >/dev/null 2>&1 - if test $? -eq 0 ; then - ERLC=erlc - AC_MSG_RESULT([yes]) - else - AC_MSG_ERROR([Cannot find erlc in path]) - fi - fi - ERLANG_ROOT_DIR=`erl -noshell -eval 'io:format("~s~n",[[code:root_dir()]])' -s erlang halt` - AC_MSG_NOTICE(ERL ROOT DIR: [$ERLANG_ROOT_DIR]) - ERLWX_VSN=`grep WX_VSN $srcdir/vsn.mk | sed 's/^.*=[ ]*//'` -else - ERLC=erlc - ERL=erl - ERLANG_ROOT_DIR=$ERL_TOP - AC_SUBST(ERLC) -fi +ERLC=erlc +ERL=erl +ERLANG_ROOT_DIR=$ERL_TOP +AC_SUBST(ERLC) AC_SUBST(WX_BUILDING_INSIDE_ERLSRC) AC_SUBST(ERLANG_ROOT_DIR) @@ -329,7 +317,7 @@ dnl dnl Check for wxwidgets dnl if test "$cross_compiling" = "yes"; then - echo "Cross compilation of the wx driver is not supported yet, wx will NOT be usable" > ./CONF_INFO + echo "Cross compilation of the wx driver is not supported yet, wx will NOT be usable" >> ./CONF_INFO WXERL_CAN_BUILD_DRIVER=false elif test X"$MIXED_CYGWIN_VC" = X"no" -a X"$MIXED_MSYS_VC" = X"no"; then WX_VERSION=`wx-config --version` @@ -398,13 +386,9 @@ define(wx_warn_text,[ wxWidgets version is $reqwx or above.]) if test "$wxWin" != 1; then - if test X"$WX_BUILDING_INSIDE_ERLSRC" != X"true" ; then - AC_MSG_ERROR([wx_warn_text]) - else - echo "wxWidgets not found, wx will NOT be usable" > ./CONF_INFO - WXERL_CAN_BUILD_DRIVER=false - AC_MSG_WARN([wx_warn_text]) - fi + echo "wxWidgets not found, wx will NOT be usable" >> ./CONF_INFO + WXERL_CAN_BUILD_DRIVER=false + AC_MSG_WARN([wx_warn_text]) fi else AC_MSG_CHECKING(for wxWidgets in standard locations) @@ -502,13 +486,9 @@ else if test -z "$WX_LIBS_STATIC"; then AC_MSG_RESULT([failed]) - if test X"$WX_BUILDING_INSIDE_ERLSRC" != X"true" ; then - AC_MSG_ERROR([Cannot find core lib version for wxWidgets]) - else - echo "No usable wxWidgets not found, wx will not be useable" > ./CONF_INFO - WXERL_CAN_BUILD_DRIVER=false - AC_MSG_WARN([Cannot find core lib version for wxWidgets]) - fi + echo "No usable wxWidgets not found, wx will not be useable" >> ./CONF_INFO + WXERL_CAN_BUILD_DRIVER=false + AC_MSG_WARN([Cannot find core lib version for wxWidgets]) fi WX_HAVE_STATIC_LIBS=true AC_SUBST(WX_CFLAGS) @@ -550,8 +530,8 @@ AC_MSG_RESULT($HAVE_GL_SUPPORT) AC_SUBST(HAVE_GL_SUPPORT) if test X"$HAVE_GL_SUPPORT" != X"yes" ; then - echo "wxWidgets don't have gl support, wx will NOT be useable" > ./CONF_INFO - WXERL_CAN_BUILD_DRIVER=false + echo "wxWidgets don't have gl support, wx will NOT be useable" >> ./CONF_INFO + WXERL_CAN_BUILD_DRIVER=false fi dnl Check for GLintptr @@ -610,7 +590,7 @@ dnl AC_CHECK_HEADERS([wx/stc/stc.h], [], [WXERL_CAN_BUILD_DRIVER=false - echo "wxWidgets don't have wxStyledTextControl (stc.h), wx will NOT be useable" > ./CONF_INFO + echo "wxWidgets don't have wxStyledTextControl (stc.h), wx will NOT be useable" >> ./CONF_INFO AC_MSG_WARN([Can not find wx/stc/stc.h $CXXFLAGS]) ], [#ifdef WIN32 @@ -670,9 +650,9 @@ AC_LANG_POP(C++) AC_MSG_RESULT($CAN_LINK_WX) if test X"$CAN_LINK_WX" != X"yes" ; then - echo "Can not link the wx driver, wx will NOT be useable" > ./CONF_INFO - WXERL_CAN_BUILD_DRIVER=false - AC_MSG_WARN([Can not link wx program are all developer packages installed?]) + echo "Can not link the wx driver, wx will NOT be useable" >> ./CONF_INFO + WXERL_CAN_BUILD_DRIVER=false + AC_MSG_WARN([Can not link wx program are all developer packages installed?]) fi fi dnl - if test "$WXERL_CAN_BUILD_DRIVER" != "false" @@ -721,6 +701,7 @@ esac AC_SUBST(SO_EXT) AC_SUBST(RUN_ERL) +AC_SUBST(CXXNOOPTFLAGS) if test X"$WX_BUILDING_INSIDE_ERLSRC" != X"true" ; then @@ -737,12 +718,6 @@ CONFIG_STATUS=$WXERL_SYS_TYPE/config.status dnl -if test X"$WX_BUILDING_INSIDE_ERLSRC" != X"true" ; then - if test X"$WXERL_CAN_BUILD_DRIVER" != X"true" ; then - AC_MSG_ERROR([Cannot build wxErlang driver, see ./CONF_INFO for information]) - fi -fi - AC_CONFIG_FILES([ config.mk c_src/Makefile @@ -750,20 +725,9 @@ AC_CONFIG_FILES([ AC_OUTPUT -if test X"$WX_BUILDING_INSIDE_ERLSRC" != X"true" ; then - AC_MSG_NOTICE() - AC_MSG_NOTICE(--------------------------------------------------) - AC_MSG_NOTICE(Using erlang compiler: [$ERLC]) - AC_MSG_NOTICE(wxErlang Install in: [$ERLANG_ROOT_DIR/lib/wx-$ERLWX_VSN]) - AC_MSG_NOTICE(Erlang driver in priv/[$WXERL_SYS_TYPE]/wxe_driver[$SO_EXT]) - AC_MSG_NOTICE(--------------------------------------------------) -fi - -if test X"$WX_BUILDING_INSIDE_ERLSRC" = X"true" ; then - CORES=`ls core* 2>/dev/null` - if test X"$CORES" != X"" ; then - echo "Configure dumped core files" > ignore_core_files - fi +CORES=`ls core* 2>/dev/null` +if test X"$CORES" != X"" ; then + echo "Configure dumped core files" > ignore_core_files fi |