Stavros Aronis | 23 Jan 14:38 2015
Picon

erl -make has unexpected return value when it fails

Hello!

Uncommon as it may be, "erl -make" is a valid way to make small projects that use an Emakefile. However, it can be the case that such a command fails:

$ erl -pa ebin -make
Recompile: src/packets
src/packets.erl:1: parameterized modules are no longer supported
src/packets.erl:10: variable 'PacketVer' is unbound

Contrary to other 'make' tools, this failure is *not* reflected in the return value of "erl -make":

$ echo $?
0

A simple way to fix this would be to add a function (say 'make:all_and_exit/0') which matches the return value of 'make:all/0' and exits with the correct code and also modify erlexec.c to call that function instead of 'make:all/0'.

Would such a patch be acceptable?

Best regards,

Stavros Aronis
_______________________________________________
erlang-bugs mailing list
erlang-bugs <at> erlang.org
http://erlang.org/mailman/listinfo/erlang-bugs
Roberto Aloi | 22 Jan 09:01 2015

Sorting order in documentation page is awkward

The following page list Erlang/OTP major releases in ascending order and minor releases in descending order. R16 sits between R7 and R8.

http://www.erlang.org/documentation.html

May I suggest descending order is used for everything, so that the further you go down in the page, the further in the past you go?

Kind regards,

Roberto

_______________________________________________
erlang-bugs mailing list
erlang-bugs <at> erlang.org
http://erlang.org/mailman/listinfo/erlang-bugs
Nico Kruber | 21 Jan 15:19 2015
Picon

Erlang problems with big binaries

I'd like to 'bor' (binary or) a big binary but the result is an empty list(?!)
Smaller binaries work as expected.

Steps to reproduce (at least on Erlang 17.4):

A=erlang:term_to_binary(lists:seq(1000000,2200000)).
B=erlang:term_to_binary(lists:seq(1000001,2200001)).
ASize=erlang:bit_size(A).
BSize=erlang:bit_size(B).
<<ANr:ASize>> = A.
<<BNr:BSize>> = B.
XNr = ANr bor BNr.
<<XNr:BSize>>.

Please note that printing the actual values of A or B is not a good idea ;)
and so would XNr but including it directly into a binary fails with the same 
error: "** exception error: bad argument"
<<(ANr bor BNr):BSize>>.

Regards
Nico Kruber
_______________________________________________
erlang-bugs mailing list
erlang-bugs <at> erlang.org
http://erlang.org/mailman/listinfo/erlang-bugs
Daniel Goertzen | 20 Jan 22:52 2015
Picon

system_info(nif_version) does not work

The documentation at...
... says I can get nif version information with erlang:system_info(nif_version).  This does not work.  See output below:



$ erl
Erlang/OTP 17 [erts-6.0.1] [source-deacab9] [64-bit] [smp:3:3] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V6.0.1  (abort with ^G)
1> erlang:system_info(nif_version).
** exception error: bad argument
     in function  erlang:system_info/1
        called as erlang:system_info(nif_version)
2>



I need nif version information because I am looking at NIF modules written in Rust.  I will run a short escript to collect config information for the Rust build.  As a work around I will look at other version information available though system_info() and make inferences about the NIF major/minor numbers.






_______________________________________________
erlang-bugs mailing list
erlang-bugs <at> erlang.org
http://erlang.org/mailman/listinfo/erlang-bugs
Nico Kruber | 20 Jan 14:24 2015
Picon

Common Test problems with includes since 17.4

Since Erlang 17.4 Common Test seems to have problems with included .hrl files 
outside of the folder the unit test resides in (even when passing the 
appropriate "include" option). The make process succeeds but when the test is 
actually run, a badarg is thrown:

EXIT, reason {{badarg,{tree,macro,{attr,0,[],none},{macro,
{var,0,'RT'},none}}},
[{erl_syntax,concrete,1,[{file,"erl_syntax.erl"},{line,6188}]},
 {erl_syntax,concrete_list,1, [{file,"erl_syntax.erl"},{line,6192}]},
 {erl_syntax,concrete_list,1, [{file,"erl_syntax.erl"},{line,6192}]},
 {erl_syntax,concrete,1,[{file,"erl_syntax.erl"},{line,6162}]},
 {erl_syntax,concrete,1,[{file,"erl_syntax.erl"},{line,6159}]},
 {erl_syntax,concrete_list,1, [{file,"erl_syntax.erl"},{line,6192}]},
 {erl_syntax,concrete_list,1, [{file,"erl_syntax.erl"},{line,6192}]},
 {erl_syntax,concrete,1,[{file,"erl_syntax.erl"},{line,6162}]}]}

== Steps to reproduce ===

* copy the attached test_SUITE.erl into a test folder and put test_SUITE.hrl 
into a sub-folder named "include"
* run any of these two commands:
ct_run -include "include" -suite test_SUITE
CT_INCLUDE_PATH=include ct_run -suite test_SUITE

=> if the .hrl file is put into the test folder, everything is fine though

Nico
Attachment (test_SUITE.erl): text/x-erlang, 202 bytes
-define(RT, rt_chord).
_______________________________________________
erlang-bugs mailing list
erlang-bugs <at> erlang.org
http://erlang.org/mailman/listinfo/erlang-bugs
Louis-Philippe Gauthier | 14 Jan 00:34 2015

hipe_mfait_lock

Hi erlang-bugs,
I couple of months ago I tried running our full application using HiPE. I ran into several issues, some manageable, some not... The most problematic issue was due to locking, specifically, the hipe_mfait_lock (you can see the lock counter output in the gist bellow).


Looking at the code it's obvious that this is a known problem... the following comment was added when the lock was added in 2010.

"XXX: Redesign apply et al to avoid those updates."

Unfortunately, I'm don't know the runtime enough to start patching it... so instead I'm reporting it.

Thanks,
LP




_______________________________________________
erlang-bugs mailing list
erlang-bugs <at> erlang.org
http://erlang.org/mailman/listinfo/erlang-bugs
Corey Cossentino | 25 Dec 06:15 2014

Different handling of floating point underflows between Linux and Solaris-based OSes

I sent this yesterday but it doesn't look like it went through, so apologies if anyone gets this twice.


Calculating math:pow(2, -1075) returns 0 on Linux, but causes an

exception on a Solaris-based system. This was causing some crashes in
RabbitMQ when it tries to calculate math:exp with inputs less than
-745.133.

Using OTP 17.4 on OmniOS r151006.

--

Erlang/OTP 17 [erts-6.3] [source] [smp:24:24] [async-threads:10]
[hipe] [kernel-poll:false]

Eshell V6.3  (abort with ^G)
1> math:pow(2, -1074.999).
5.0e-324
2> math:pow(2, -1074) * math:pow(2, -1).
0.0
3> math:pow(2, -1075).
** exception error: an error occurred when evaluating an arithmetic expression
     in function  math:pow/2
        called as math:pow(2,-1075)
4> math:exp(-745).
5.0e-324
5> math:exp(-746).
** exception error: an error occurred when evaluating an arithmetic expression
     in function  math:exp/1
        called as math:exp(-746)

--


Running this in gdb, it looks like the matherr function in
sys/unix/sys_float.c is being called on Solaris but not on Linux,
possibly because the Linux version of libm requires the _SVID_SOURCE
feature test macro in order to call the function (
http://man7.org/linux/man-pages/man3/matherr.3.html ).

OmniOS (Solaris libm):
--

0xfeeba733 in ?? () from /lib/libm.so.2
(gdb)
0xfeeb63c0 in matherr <at> plt () from /lib/libm.so.2
(gdb)
matherr (exc=0xfdeffdac) at sys/unix/sys_float.c:839
839     {
(gdb)

--


Linux:
--

0x00007fb6a1d0e9a7 in pow () from /lib/x86_64-linux-gnu/libm.so.6
(gdb)
0x00007fb6a1ced550 in matherr <at> plt () from /lib/x86_64-linux-gnu/libm.so.6
(gdb)
0x00007fb6a1d33f00 in ?? () from /lib/x86_64-linux-gnu/libm.so.6
(gdb)
_______________________________________________
erlang-bugs mailing list
erlang-bugs <at> erlang.org
http://erlang.org/mailman/listinfo/erlang-bugs
Jesper Louis Andersen | 16 Dec 01:07 2014
Picon

Dialyzer can't compile map correctly

Hi OTP team and other interested parties.

While I was building up the enacl application, I have discovered a problem where I can crash the dialyzer. Attached are two minimized files which exposes the problem. To compile this I did:

erlc +debug_info *.erl
dialyzer --build_plt --apps kernel stdlib
dialyzer *.beam

and it produces the following IDE (Internal Dialyzer Error):

erlc +debug_info *.erl
dialyzer *.beam
  Checking whether the PLT /home/jlouis/.dialyzer_plt is up-to-date... yes
  Proceeding with analysis...
=ERROR REPORT==== 16-Dec-2014::01:00:27 ===
Error in process <0.48.0> with exit value: {{case_clause,map},[{dialyzer_dataflow,find_terminals,1,[{file,"dialyzer_dataflow.erl"},{line,3451}]},{dialyzer_dataflow,find_terminals_list,3,[{file,"dialyzer_dataflow.erl"},{line,3504}]},{dialyzer_dataflow,classify_returns... 


dialyzer: Analysis failed with error:
{{case_clause,map},
 [{dialyzer_dataflow,find_terminals,1,
                     [{file,"dialyzer_dataflow.erl"},{line,3451}]},
  {dialyzer_dataflow,find_terminals_list,3,
                     [{file,"dialyzer_dataflow.erl"},{line,3504}]},
  {dialyzer_dataflow,classify_returns,1,
                     [{file,"dialyzer_dataflow.erl"},{line,3443}]},
  {dialyzer_dataflow,'-state__get_warnings/2-fun-0-',7,
                     [{file,"dialyzer_dataflow.erl"},{line,2908}]},
  {lists,foldl,3,[{file,"lists.erl"},{line,1261}]},
  {dialyzer_dataflow,state__get_warnings,2,
                     [{file,"dialyzer_dataflow.erl"},{line,2934}]},
  {dialyzer_dataflow,get_warnings,5,
                     [{file,"dialyzer_dataflow.erl"},{line,142}]},
  {dialyzer_succ_typings,collect_warnings,2,
                         [{file,"dialyzer_succ_typings.erl"},{line,182}]}]}
Last messages in the log cache:
  Reading files and computing callgraph... done in 0.06 secs
  Removing edges... done in 0.01 secs
Makefile:2: recipe for target 'all' failed
make: *** [all] Error 1

I have attached the two culprit files. They have the following sizes:

jlouis <at> eldar:~/tmp/problem$ wc *.erl
 12  29 211 enacl.erl
 23  36 460 enacl_nif.erl
 35  65 671 total

and I think it may be possible to shrink further down, but I think it is already small enough to be workable. Do note: while one part is a NIF, you don't need the underlying C code to break the dialyzer.

The full repository is at:


and the commit ID 23e535fcc23c1 should have the error if you want to look at the full repository. It does require a properly installed libsodium, which is not in Debian/Ubuntu for instance, which is why I have tried to narrow down the problem before reporting it.

I hope this is enough to track down the error, perhaps by looking at the backtrace and error case alone. Otherwise, please come back to me.
 
--
J.
Attachment (enacl.erl): text/x-erlang, 287 bytes
Attachment (enacl_nif.erl): text/x-erlang, 624 bytes
_______________________________________________
erlang-bugs mailing list
erlang-bugs <at> erlang.org
http://erlang.org/mailman/listinfo/erlang-bugs
Mikael Pettersson | 15 Dec 13:16 2014
Picon

SEGV in process_main() line 3163 [r15B03]

[2nd attempt to send this, my apologies if you seee this twice]

We've had two segfaults now in r15's process_main(), line 3163, which is
the register flushing loop just before the current process is swapped out:

==snip==
     argp = c_p->arg_reg;
     for (i = c_p->arity - 1; i > 0; i--) {
=>       argp[i] = reg[i];
     }
     c_p->arg_reg[0] = r(0);
     SWAPOUT;
==snip==

The core file is unfortunately truncated: I can see the registers at the
point of the SEGV, but not inspect any memory.  The registers and
disassembly are:

==snip==
Program terminated with signal 11, Segmentation fault.
#0  process_main () at beam/beam_emu.c:3163
3163    beam/beam_emu.c: No such file or directory.
(gdb) info reg
rax            0x7e7d77fff3f8   139077349274616
rbx            0x7f243b82feb8   139793593990840
rcx            0x0      0
rdx            0x53ba78 5487224
rsi            0x7e7d75622030   139077305376816
rdi            0x0      0
rbp            0x1414400        0x1414400
rsp            0x7f2467432cf0   0x7f2467432cf0
r8             0x0      0
r9             0x0      0
r10            0x0      0
r11            0x246    582
r12            0x7f2471b407c8   139794503174088
r13            0x7e7f4309cae0   139085050661600
r14            0x7e7f42e57168   139085048279400
r15            0xc63f   50751
rip            0x5425e4 0x5425e4 <process_main+29892>
eflags         0x10202  [ IF RF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) disassemble 0x5425a6,0x542610
Dump of assembler code from 0x5425a6 to 0x542610:
   0x00000000005425a6 <process_main+29830>:     mov    0x90(%rbp),%rdx
   0x00000000005425ad <process_main+29837>:     mov    %rax,0x98(%rbp)
   0x00000000005425b4 <process_main+29844>:     mov    %edx,0xa0(%rbp)
   0x00000000005425ba <process_main+29850>:     mov    0xd0(%rbp),%rcx
   0x00000000005425c1 <process_main+29857>:     lea    -0x1(%rdx),%eax
   0x00000000005425c4 <process_main+29860>:     mov    0x98(%rbp),%rsi
   0x00000000005425cb <process_main+29867>:     test   %eax,%eax
   0x00000000005425cd <process_main+29869>:     mov    %rcx,0x48(%rsp)
   0x00000000005425d2 <process_main+29874>:     jle    0x5425fd <process_main+29917>
   0x00000000005425d4 <process_main+29876>:     cltq
   0x00000000005425d6 <process_main+29878>:     sub    $0x2,%edx
   0x00000000005425d9 <process_main+29881>:     shl    $0x3,%rax
   0x00000000005425dd <process_main+29885>:     add    %rax,%r12
   0x00000000005425e0 <process_main+29888>:     lea    (%rsi,%rax,1),%rax
=> 0x00000000005425e4 <process_main+29892>:     mov    (%r12),%rcx
   0x00000000005425e8 <process_main+29896>:     sub    $0x1,%edx
   0x00000000005425eb <process_main+29899>:     sub    $0x8,%r12
   0x00000000005425ef <process_main+29903>:     mov    %rcx,(%rax)
   0x00000000005425f2 <process_main+29906>:     lea    0x1(%rdx),%ecx
   0x00000000005425f5 <process_main+29909>:     sub    $0x8,%rax
   0x00000000005425f9 <process_main+29913>:     test   %ecx,%ecx
   0x00000000005425fb <process_main+29915>:     jg     0x5425e4 <process_main+29892>
   0x00000000005425fd <process_main+29917>:     mov    %r15,(%rsi)
   0x0000000000542600 <process_main+29920>:     mov    %r14,0x0(%rbp)
   0x0000000000542604 <process_main+29924>:     mov    $0x8,%esi
   0x0000000000542609 <process_main+29929>:     mov    %r13,0x8(%rbp)
   0x000000000054260d <process_main+29933>:     mov    %rbx,0xe0(%rbp)
End of assembler dump.
==snip==

I interpret this as follows:
1. c_p == %rbp == 0x1414400
2. &argp[i] == %rax == 0x7e7d77fff3f8
   from this I deduce that c_p->arg_reg != c_p->def_arg_reg, so it points
   to a dynamically allocated area separate from *c_p
3. i == c_p->arity - 1 == %rdx == 0x53ba78
   this is clearly bonkers, and what's causing references into unmapped
   memory
4. &reg[i] == %r12 == 0x7f2471b407c8
   this is consistent with indexing a frame-local array at 0x53ba78

Basically, my conclusion is that c_p->arity has been clobbered, causing
out-of-range accesses in this loop.

We've had this exact crash twice now, in August and last Thursday (Dec 11).

I realize the lack of a complete core dump makes this impossible to debug.
What I'm hoping for is that someone might recollect some post-R15 change
or fix that might have something to do with unexpected clobbers of process
structs.

/Mikael
_______________________________________________
erlang-bugs mailing list
erlang-bugs <at> erlang.org
http://erlang.org/mailman/listinfo/erlang-bugs

Vladislav Titov | 10 Dec 17:58 2014

Mnesia:add_table_copy causes crashes when no replicas available

Hi

This is on a fully in-RAM mnesia cluster.

When performing mnesia:add_table_copy(tab, node(), ram_copies) when no active replicas of tab are available, it replies back correctly with {aborted, {system_limit, tab, ...}}.

However, looking at the mnesia_gvar afterwards, the {schema, local_tables} key lists the table in it.

This (?) then causes mnesia to shut down when a node that is listed as having the table gets started and adopts it as an orphan. In R14 (our target release for now):

FATAL ** Sender failed: {error, {no_exists, tab}}

Or in R17:

FATAL ** Cannot load table foo from disc: {not_loaded, storage_unknown}

This then causes mnesia to shutdown.

The R14 case only happens if the node listed as actually holding the table starts, and then re-starts. In R17 it seems to happen straight away on first startup.

The active_replicas option for the table ends up listing the node() as well at some point.

I've attached a repo case.

Any idea how I can work around this? Obviously checking active_replicas before a copy would be a good idea, but it wouldn't protect against race conditions when nodes are yo-yoing. Would cleaning up the local_tables gvar be a good idea if system_limit happens?

thanks,
vlad 



Attachment (bug_add_table_copy.escript): application/octet-stream, 2524 bytes
_______________________________________________
erlang-bugs mailing list
erlang-bugs <at> erlang.org
http://erlang.org/mailman/listinfo/erlang-bugs
Slava Yurin | 10 Dec 08:03 2014
Picon

gen_tcp:send and file:sendfile

Hi all.
 
I have error behavior of gen_tcp:send/2 + file:sendfile/5.
 
If data for send falls into buffer in port and happen file:sendfile/5 call, then
buffer not flushed and data from file send. After that any call gen_tcp:send/2
only append data to buffer and not send anything. And if not set send_timeout
option gen_tcp:send will hang after exceed size of buffer. This is my guess.
 
I attach test file and log of it usage.
 
Have reproducible error only when [{delay_send, true}, {nodelay, false}], but in
real usage see same behavior without this options. Can't reproduce it on
localhost and 1 file.
Attachment (send_file_test.erl): application/octet-stream, 1657 bytes
v.yurin <at> hell:~$ uname -a
Linux hell 3.17.3-1-ARCH #1 SMP PREEMPT Fri Nov 14 23:13:48 CET 2014 x86_64 GNU/Linux
v.yurin <at> hell:~/test$ erl
Erlang/OTP 17 [erts-6.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V6.2  (abort with ^G)
1> L = send_file_test:start().
Listen on 59690
#Port<0.563>
2> send_file_test:one_client(L, [], 1).
ok
Send file 1
3> send_file_test:one_client(L, [{delay_send, true}, {nodelay, false}], 1). 
ok
Send file 1
4> send_file_test:one_client(L, [{delay_send, true}, {nodelay, false}, {send_timeout, 1000}],
200).                                                        
ok
Send file 200
Send file 199
Send file 198
Send file 197
Send file 196
Send file 195
Send file 194
Send file 193
Send file 192
Send file 191
Send file 190
Send file 189
Send file 188
Send file 187
Send file 186
Send file 185
Send file 184
Send file 183
Send file 182
Send file 181
Send file 180
Send file 179
Send file 178
Send file 177
Send file 176
Send file 175
Send file 174
Send file 173
Send file 172
Send file 171
Send file 170
Send file 169
Send file 168
Send file 167
Send file 166
Send file 165
Send file 164
Send file 163
Send file 162
Send file 161
Send file 160
Send file 159
Send file 158
Send file 157
Send file 156
Send file 155
Send file 154
Send file 153
Send file 152
Send file 151
Send file 150
Send file 149
Send file 148
Send file 147
Send file 146
Send file 145
Send file 144
Send file 143
Send file 142
Send file 141
Send file 140
Send file 139
Send file 138
Send file 137
Send file 136
Send file 135
Send file 134
Send file 133
Send file 132
Send file 131
Send file 130
Send file 129
Send file 128
Send file 127
Send file 126
Send file 125
Send file 124
Send file 123
Send file 122
Send file 121
Send file 120
Send file 119
Send file 118
Send file 117
Send file 116
Send file 115
Send file 114
Send file 113
Send file 112
Send file 111
Send file 110
Send file 109
Send file 108
Send file 107
Send file 106
Send file 105
Send file 104
Send file 103
Send file 102
Send file 101
Send file 100
Send file 99
Send file 98
Send file 97
Send file 96
Send file 95
Send file 94
Send file 93
Send file 92
Send file 91
Send file 90
Send file 89
Send file 88
Send file 87
Send file 86
Send file 85
Send file 84
Send file 83
5> 
=ERROR REPORT==== 10-Dec-2014::12:45:28 ===
Error in process <0.40.0> with exit value: {{badmatch,{error,timeout}},[{send_file_test,loop,3,[{file,"send_file_test.erl"},{line,37}]}]}

5> send_file_test:one_client(L, [{delay_send, true}, {nodelay, false}], 200).       ok             
Send file 200
Send file 199
Send file 198
Send file 197
Send file 196
Send file 195
Send file 194
Send file 193
Send file 192
Send file 191
Send file 190
Send file 189
Send file 188
Send file 187
Send file 186
Send file 185
Send file 184
Send file 183
Send file 182
Send file 181
Send file 180
Send file 179
Send file 178
Send file 177
Send file 176
Send file 175
Send file 174
Send file 173
Send file 172
Send file 171
Send file 170
Send file 169
Send file 168
Send file 167
Send file 166
Send file 165
Send file 164
Send file 163
Send file 162
Send file 161
Send file 160
Send file 159
Send file 158
Send file 157
Send file 156
Send file 155
Send file 154
Send file 153
Send file 152
Send file 151
Send file 150
Send file 149
Send file 148
Send file 147
Send file 146
Send file 145
Send file 144
Send file 143
Send file 142
Send file 141
Send file 140
Send file 139
Send file 138
Send file 137
Send file 136
Send file 135
Send file 134
Send file 133
Send file 132
Send file 131
Send file 130
Send file 129
Send file 128
Send file 127
Send file 126
Send file 125
Send file 124
Send file 123
Send file 122
Send file 121
Send file 120
Send file 119
Send file 118
Send file 117
Send file 116
Send file 115
Send file 114
Send file 113
Send file 112
Send file 111
Send file 110
Send file 109
Send file 108
Send file 107
Send file 106
Send file 105
Send file 104
Send file 103
Send file 102
Send file 101
Send file 100
Send file 99
Send file 98
Send file 97
Send file 96
Send file 95
Send file 94
Send file 93
Send file 92
Send file 91
Send file 90
Send file 89
Send file 88
Send file 87
Send file 86
Send file 85
Send file 84
Send file 83
6> now().
{1418,194038,215600}
7> now().
{1418,194077,282560}
8> "send hang ...".
v.yurin <at> hell:~$ telnet 127.0.0.1 59690
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
start
Some data before file
File 1:
%%  <at> author Slava Yurin <YurinVV <at> ya.ru>
%%  <at> doc Test Sendfile
-module(send_file_test).

-export([one_client/3]).
-export([start/0]).

start() ->
	{ok, Listen} = gen_tcp:listen(0, [{active, false}, {ip, {127, 0, 0, 1}}]),
	{ok, Port} = inet:port(Listen),
	io:format("Listen on ~p~n", [Port]),
	Listen.

one_client(Listen, Opt, FileCount) ->
	{ok, Client} = gen_tcp:accept(Listen),
	%Opt = [{delay_send, false}, {nodelay, true}],
	%Opt = [{delay_send, true}, {nodelay, false}],
	ok = inet:setopts(Client, [binary, {packet, line}, {active, false} | Opt]),
	Pid = spawn(fun() -> loop(Client, FileCount) end),
	ok = gen_tcp:controlling_process(Client, Pid),
	Pid ! start,
	ok.

loop(Client, FileCount) ->
	receive start -> ok end,
	{ok, <<"start\r\n">>} = gen_tcp:recv(Client, 0),
	{ok, FD} = file:open("send_file_test.erl", [raw, read, binary]),
	loop(Client, FD, FileCount).

loop(_, _, 0) ->
	ok;
loop(Client, FD, Pos) ->
	io:format("Send file ~p~n", [Pos]),
	ok = gen_tcp:send(Client,
		["Some data before file\r\nFile ", integer_to_list(Pos), ":\r\n"]),
	{ok, _} = file:sendfile(FD, Client, 0, 0, []),
	ok = gen_tcp:send(Client, ["File ", integer_to_list(Pos), " end\r\nSome data after file\r\n"]),
	loop(Client, FD, Pos - 1).
File 1 end
Some data after file
Connection closed by foreign host.
v.yurin <at> hell:~$ telnet 127.0.0.1 59690
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
start
%%  <at> author Slava Yurin <YurinVV <at> ya.ru>
%%  <at> doc Test Sendfile
-module(send_file_test).

-export([one_client/3]).
-export([start/0]).

start() ->
	{ok, Listen} = gen_tcp:listen(0, [{active, false}, {ip, {127, 0, 0, 1}}]),
	{ok, Port} = inet:port(Listen),
	io:format("Listen on ~p~n", [Port]),
	Listen.

one_client(Listen, Opt, FileCount) ->
	{ok, Client} = gen_tcp:accept(Listen),
	%Opt = [{delay_send, false}, {nodelay, true}],
	%Opt = [{delay_send, true}, {nodelay, false}],
	ok = inet:setopts(Client, [binary, {packet, line}, {active, false} | Opt]),
	Pid = spawn(fun() -> loop(Client, FileCount) end),
	ok = gen_tcp:controlling_process(Client, Pid),
	Pid ! start,
	ok.

loop(Client, FileCount) ->
	receive start -> ok end,
	{ok, <<"start\r\n">>} = gen_tcp:recv(Client, 0),
	{ok, FD} = file:open("send_file_test.erl", [raw, read, binary]),
	loop(Client, FD, FileCount).

loop(_, _, 0) ->
	ok;
loop(Client, FD, Pos) ->
	io:format("Send file ~p~n", [Pos]),
	ok = gen_tcp:send(Client,
		["Some data before file\r\nFile ", integer_to_list(Pos), ":\r\n"]),
	{ok, _} = file:sendfile(FD, Client, 0, 0, []),
	ok = gen_tcp:send(Client, ["File ", integer_to_list(Pos), " end\r\nSome data after file\r\n"]),
	loop(Client, FD, Pos - 1).
Connection closed by foreign host.
v.yurin <at> hell:~$ telnet 127.0.0.1 59690
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
start

[ ... skip ... ]

%%  <at> author Slava Yurin <YurinVV <at> ya.ru>
%%  <at> doc Test Sendfile
-module(send_file_test).

-export([one_client/3]).
-export([start/0]).

start() ->
	{ok, Listen} = gen_tcp:listen(0, [{active, false}, {ip, {127, 0, 0, 1}}]),
	{ok, Port} = inet:port(Listen),
	io:format("Listen on ~p~n", [Port]),
	Listen.

one_client(Listen, Opt, FileCount) ->
	{ok, Client} = gen_tcp:accept(Listen),
	%Opt = [{delay_send, false}, {nodelay, true}],
	%Opt = [{delay_send, true}, {nodelay, false}],
	ok = inet:setopts(Client, [binary, {packet, line}, {active, false} | Opt]),
	Pid = spawn(fun() -> loop(Client, FileCount) end),
	ok = gen_tcp:controlling_process(Client, Pid),
	Pid ! start,
	ok.

loop(Client, FileCount) ->
	receive start -> ok end,
	{ok, <<"start\r\n">>} = gen_tcp:recv(Client, 0),
	{ok, FD} = file:open("send_file_test.erl", [raw, read, binary]),
	loop(Client, FD, FileCount).

loop(_, _, 0) ->
	ok;
loop(Client, FD, Pos) ->
	io:format("Send file ~p~n", [Pos]),
	ok = gen_tcp:send(Client,
		["Some data before file\r\nFile ", integer_to_list(Pos), ":\r\n"]),
	{ok, _} = file:sendfile(FD, Client, 0, 0, []),
	ok = gen_tcp:send(Client, ["File ", integer_to_list(Pos), " end\r\nSome data after file\r\n"]),
	loop(Client, FD, Pos - 1).
Connection closed by foreign host.
v.yurin <at> hell:~$ telnet 127.0.0.1 59690
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
start

[ ... skip ... ]

%%  <at> author Slava Yurin <YurinVV <at> ya.ru>
%%  <at> doc Test Sendfile
-module(send_file_test).

-export([one_client/3]).
-export([start/0]).

start() ->
	{ok, Listen} = gen_tcp:listen(0, [{active, false}, {ip, {127, 0, 0, 1}}]),
	{ok, Port} = inet:port(Listen),
	io:format("Listen on ~p~n", [Port]),
	Listen.

one_client(Listen, Opt, FileCount) ->
	{ok, Client} = gen_tcp:accept(Listen),
	%Opt = [{delay_send, false}, {nodelay, true}],
	%Opt = [{delay_send, true}, {nodelay, false}],
	ok = inet:setopts(Client, [binary, {packet, line}, {active, false} | Opt]),
	Pid = spawn(fun() -> loop(Client, FileCount) end),
	ok = gen_tcp:controlling_process(Client, Pid),
	Pid ! start,
	ok.

loop(Client, FileCount) ->
	receive start -> ok end,
	{ok, <<"start\r\n">>} = gen_tcp:recv(Client, 0),
	{ok, FD} = file:open("send_file_test.erl", [raw, read, binary]),
	loop(Client, FD, FileCount).

loop(_, _, 0) ->
	ok;
loop(Client, FD, Pos) ->
	io:format("Send file ~p~n", [Pos]),
	ok = gen_tcp:send(Client,
		["Some data before file\r\nFile ", integer_to_list(Pos), ":\r\n"]),
	{ok, _} = file:sendfile(FD, Client, 0, 0, []),
	ok = gen_tcp:send(Client, ["File ", integer_to_list(Pos), " end\r\nSome data after file\r\n"]),
	loop(Client, FD, Pos - 1).
_______________________________________________
erlang-bugs mailing list
erlang-bugs <at> erlang.org
http://erlang.org/mailman/listinfo/erlang-bugs

Gmane