Age | Commit message (Collapse) | Author |
|
If a behaviour module contains an non-exported function with the same name as
one of the behaviour's callbacks, the callback info was inadvertently deleted
from the PLT as the dialyzer_plt:delete_list/2 function was cleaning up the
callback table. This bug was reported by Brujo Benavides.
Fixes ERL-72 bug report.
|
|
|
|
Dialyzer used to report unknown behaviours in the same way as unknown
functions and types. This functionality has been removed in d101155, but
some code remained.
|
|
The following code would crash v3_codegen:
order(From) ->
catch
if
From#{[] => sufficient} ->
saint
end.
Before explaining the crash, first some background on the stack
frame and the Y registers.
Certain instructions, most notably the 'call' instructions, clobber
all X registers. Before any such instruction, all X registers that
have values that will be used after the call must be saved to Y
registers (i.e. to the stack frame). adjust_stack/4 will be called
when X registers must be saved.
There is also another situation when X registers must be saved, namely
within a 'catch' if we are about to execute any instruction that may
cause an exception. Examples of such instructions are some guard BIFs
(such as length/1) and construction of binaries or maps. Within a
'catch', X registers must be be saved because if an exception is
thrown and catched all X registers will be destroyed. The same
adjust_stack/4 function will be called for those instructions, but
only if they occur within a 'catch'.
There is actually one more complication. If there is code in
a guard within a catch, the X registers should not be saved, because
the code in a guard never clobbers any X registers that were alive
before the guard code was entered. v3_codegen is written with the
implicit assumption that code in guards never cause anything
to be saved to Y registers.
The code for building maps and binaries would incorrectly save X
registers within a guard inside a 'catch'.
For construction of binaries, that would mean that a useless but
harmelss 'move' instruction was generated.
But for construction of maps, the saving of the Y register would not
be harmless. There would be a crash when attempting to merge #sr{}
records. #sr{} records keeps track of the contents of X and Y
registers. When two separate code paths are joined (e.g. at the end of
'case' statement), the register descriptors must be reconciled.
Basically, the register descriptors for both paths must be identical.
The #sr{} record for one path must not claim that {y,0} contains
a certain value, while another path claims that {y,0} is dead.
Thus, the crash occurs in sr_merge/2 when failing to reconcile the
Y registers.
To fix this bug this bug we will introduce a new function called
maybe_adjust_stack/5. It will save X registers on the stack only
if the code is inside a catch but not inside a guard. We will
change all existing code to use this new function when appropriate.
Reported-by: Thomas Arts
|
|
|
|
|
|
* hans/ssh/keyboard_interactive0/OTP-13255:
ssh: update vsn.mk to 4.2.1
ssh: handle secondary ssh_msg_userauth_info_request message
ssh: testcase for abnormal keyboard-interactive authentication
|
|
|
|
|
|
|
|
* bjorn/compiler/beam_bool/OTP-13208:
beam_bool: Fix unsafe optimization
|
|
beam_bool would make the following code unsafe (which would be
reported by beam_validator):
scotland(Echo) ->
found(case Echo of
Echo when true; Echo, Echo, Echo ->
Echo;
echo ->
[]
end,
Echo = placed).
found(_, _) -> million.
Basically, beam_bool would see that the 'case' would always return
the value of Echo. Thus:
scotland(Echo) ->
found(Echo, Echo = placed).
The only problem is that beam_bool would also remove a 'move'
instruction that would save Echo to the stack. Here is the
assembly code for part of the function:
{allocate_zero,1,1}.
{move,{x,0},{y,0}}. %% Save Echo on stack.
{bif,'=:=',{f,7},[{x,0},{atom,true}],{x,1}}.
{bif,'=:=',{f,7},[{x,0},{atom,true}],{x,2}}.
{bif,'=:=',{f,7},[{x,0},{atom,true}],{x,3}}.
{bif,'and',{f,7},[{x,2},{x,3}],{x,2}}.
{bif,'and',{f,7},[{x,1},{x,2}],{x,1}}.
{jump,{f,8}}.
{label,7}.
{move,{atom,false},{x,1}}.
{label,8}.
{bif,'or',{f,6},[{atom,true},{x,1}],{x,1}}.
{test,is_eq_exact,{f,6},[{x,1},{atom,true}]}. %% Jump never taken.
{jump,{f,5}}.
{label,6}.
{test,is_eq_exact,{f,9},[{x,0},{atom,echo}]}.
{move,nil,{x,0}}.
{jump,{f,5}}.
{label,9}.
{test_heap,3,0}.
{put_tuple,2,{x,0}}.
{put,{atom,case_clause}}.
{put,{y,0}}.
{line,[{location,"t.erl",5}]}.
{call_ext,1,{extfunc,erlang,error,1}}.
{jump,{f,5}}.
{label,5}.
{test,is_eq_exact,{f,12},[{atom,placed},{y,0}]}.
beam_bool would see that the is_eq_exact test at label 8 would
always succeed. It could therefore remove most of the code before
the jump to label 5. Unfortunately it also removed the essential
move of Echo to the stack:
{allocate_zero,1,1}.
%% Instruction incorrectly removed: {move,{x,0},{y,0}}.
{jump,{f,5}}.
{label,5}.
{test,is_eq_exact,{f,12},[{atom,placed},{y,0}]}.
The root cause of the problem is that the 'move' instruction is
included in the block of 'bif' instructions before label 8.
Normally the 'move' instruction would not have been discarded,
but because the left operand to the 'or' BIF is 'true', the
entire block with 'bif' instructions are dropped.
As far as I can see, there is no gain by including 'move'
instructions in the first place. There is no way that better
code will be produced. In fact, the entire optimization can
be given up if 'move' instructions are found in the block.
Thus we can fix this bug by never including any 'move' instructions
in the block of 'bif' instructions. We can also remove all the
code that deals with 'move' instructions within blocks.
Reported-by: Thomas Arts
|
|
Today, if you press Ctrl+W inside erl, it will erase word chars including dots.
This may have made sense in the past when Erlang had packages, but today
considering the most common case for dots inside erl is to work with records,
considering the dot part of the word is rather a mistake.
For example, imagine the following code, where [] is the cursor:
1> S#elixir_scope.name[]
When I press Ctrl+W it erases all up to #:
1> S#[]
This patch changes it to the dot is no longer considered part of the name:
1> S#elixir_scope.[]
Which is rather expected behaviour for most use cases of dot in Erlang.
|
|
* rickard/rq-len/OTP-13201:
Light weight statistics of run queue lengths
|
|
- statistics(total_run_queue_lengths)
- statistics(run_queue_lengths)
- statistics(total_active_tasks)
- statistics(active_tasks)
Conflicts:
erts/emulator/beam/erl_process.c
|
|
* rickard/trace_call_time/OTP-13216:
Use monotonic time for call_time trace
|
|
|
|
|
|
|
|
* zandra/update-java-versions-doc:
update java version in documentation
OTp-13221
|
|
* binarin/maint:
Don't wait for twice the delay_write timeout
OTP-13220
|
|
* legoscia/tls_dist_error_reporting:
Report bad options for outgoing TLS distribution
Save error reasons for TLS distribution connections
Report bad options for TLS distribution connections
OTP-13219
|
|
* josevalim/jv-map-fun-eval-maint:
Use full list of bindings when matching on map keys
OTP-13218
|
|
* lucafavatella/dialyzer-fun-call:
Teach Dialyzer call to funs `M:F/A` (literal M, F, A)
OTP-13217
|
|
192c4a80c broke the build on at least Debian/Hurd and Debian/kFreeBSD,
because it's not linux but still using glibc. To fix it, test for
__GLIBC__ in addition to __linux__.
|
|
This reverts commit 192c4a80c7d6fe9949aecb864901c4a3d9549f36.
This breaks on Debian/Hurd, Debian/kFreeBSD, and possibly other
platforms as well. Will be solved differently in a follow-up commit.
|
|
|
|
|
|
* hans/ssh/ssh_benchmark_SUITE:
ssh: clean test specs
|
|
|
|
* hans/ssh/cuddle_tests:
ssh: add econnaborted to disconnect msgs in test suite
ssh: fix the check that open-ssh supports certain pubkeys in a test suite
|
|
* hans/ssh/ssh_benchmark_SUITE:
ssh: fix error (wrong suite) in test/ssh.spec
|
|
|
|
The nature of aux work is such that dirty schedulers should not
attempt to perform it. Modify the code to ensure that dirty schedulers
avoid aux work.
Also fix an incorrect assumption about the size of a Uint in the
ErtsDirtySchedId type.
|
|
Each service process maintains a dictionary of peers, mapping an
application alias to a {pid(), #diameter_caps{}} list of connected
peers. These lists are potentially large, peers were appended to the end
of the list for no particular reason, and these long lists were
constructed/deconstructed when filtering them for pick_peer callbacks.
Many simultaneous outgoing request could then slow the VM to a crawl,
with many scheduled processes mired in list manipulation.
The pseudo-dicts are now replaced by plain ets tables. The reason for
them was (once upon a time) to have an interface interchangeable with a
plain dict for debugging purposes, but strict swapablity hasn't been the
case for some time now, and in practice a swap has never taken place.
Additional tables mapping Origin-Host/Realm have also been introduced,
to minimize the size of the peers lists when peers are filtered on
host/realm. For example, a filter like
{any, [{all, [realm, host]}, realm]}
is probably a very common case: preferring a Destination-Realm/Host
match before falling back on Destination-Realm alone. This is now more
efficiently (but not equivalently) expressed as
{first, [{all, [realm, host]}, realm]}
to stop the search when the best match is made, and extracts peers from
host/realm tables instead of searching through the list of all peers
supporting the application in question. The code to try and start with a
lookup isn't exhaustive, and the 'any' filter is still as inefficient as
previously.
|
|
See commit 862af31d.
|
|
|
|
OTP-13164 more efficient peer lists
One module. Downgrade not supported.
|
|
|
|
* hans/ssh/ssh_benchmark_SUITE:
ssh: benchmark all common kex and cipher algorithms
New structure of the report
ssh: ssh_benchmark_SUITE re-organized
ssh: Add first version of ssh_benchmark_SUITE
|
|
|
|
|
|
|
|
|
|
Compiling OTP 18.2.1 with gcc-5.3 shows the following warning:
drivers/common/efile_drv.c:1538:23: warning: logical not is only applied to the left hand side of comparison [-Wlogical-not-parentheses]
The code in question is:
if (! (status =
erts_gzwrite((ErtsGzFile)d->fd,
iov[i].iov_base,
iov[i].iov_len)) == iov[i].iov_len) {
d->errInfo.posix_errno =
d->errInfo.os_errno = errno; /* XXX Correct? */
break;
}
If we hoist the assignment out of the if for clarity, it becomes:
status = erts_gzwrite(..., iov[i].iov_len);
if (! status == iov[i].iov_len) { ...; break; }
iov_len is > 0 here, and status will equal iov_len if erts_gzwrite
succeeded, but will be less than iov_len if an error occurred.
"! status" is 0 or 1, which can only equal iov_len if iov_len is 1 and
erts_gzwrite detected an error and returned 0.
The effect of this mistake is that any error when iov_len >= 2 will
skip the conditional code and break statement. In particular, partial
writes (0 < status && status < iov_len) will not be flagged as errors.
All releases since OTP R8B-0 are affected.
The variable "status" is really a boolean, which is to be set to zero
on error. The fix is to set status to 1 if erts_gzwrite() returned iov_len
and 0 otherwise, and to change the condition to "if (! status) ...".
I'm also hoisting the assignment out of the condition since it obscures
the code while providing not benefit (the condition in a while or for
loop would be a different matter).
|
|
|
|
|
|
* anders/diameter/17.5.6.7/OTP-13211:
vsn -> 1.9.2.2
Update/fix appup for 17.5.6.7
Be resilient to diameter_service state upgrades
|
|
* anders/diameter/request_leak/OTP-13137:
Fix request table leak at retransmission
Fix request table leak at exit signal
|
|
* anders/diameter/17/watchdog/OTP-12969:
Fix watchdog function_clause
|