How do unix domain sockets work in Erlang 19 - erlang

I tried a few things but I'm not able to read anything from them
{ok, Port} = gen_udp:open(0, [{ifaddr,{local,"/tmp/socket2"}}]).
Then I switch to console.
echo "hi" | socat - UNIX-CONNECT:/tmp/socket2
Back to erlang
41> gen_udp:recv(Port, 2, 5000).
{error,timeout}
Any help is appreciated. I've also tried {active, true} opt and flush(). shows nothing.

I've not tried the official release 19, but I can make it work using the latest git (as of July 7th) by:
disabling active with {active, false}
using UNIX-SENDTO instead of UNIX-CONNECT
binding socat's socket to its own address (not binding creates an error on erlangs side when resolving the address.)
Demonstration:
console 1:
$ rm /tmp/socket*
$ erl
Erlang/OTP 19 [erts-8.0.1] [source-ca40008] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V8.0.1 (abort with ^G)
1> {ok, Port} = gen_udp:open(0, [{active, false},{ifaddr, {local,"/tmp/socket2"}}]),
1> io:format("ok~w ~w~n", [ok,Port]),
1> gen_udp:recv(Port, 2).
okok #Port<0.451>
console 2:
$ echo "hi" | socat - UNIX-SENDTO:/tmp/socket2,bind=/tmp/socket1
console 1 results:
okok #Port<0.451>
{ok,{{local,<<"/tmp/socket1">>},0,"hi\n"}}

Related

What does "Class FIFinderSyncExtensionHost is implemented in both mean" when running crashdump_viewer?

I started the crashdump_viewer and started looking at my crashdump. Then at some point I got an error log. What does this mean and how do I fix it?
➜ Desktop erl
Erlang/OTP 21 [erts-10.3.5.11] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [hipe] [dtrace]
Eshell V10.3.5.11 (abort with ^G)
1> l(crashdump_viewer).
{module,crashdump_viewer}
2> crashdump_viewer:st
start/0 start/1 start_link/0 stop/0 stop_debug/0
2> crashdump_viewer:start
start/0 start/1 start_link/0
2> crashdump_viewer:start().
objc[26293]: Class FIFinderSyncExtensionHost is implemented in both /System/Library/PrivateFrameworks/FinderKit.framework/Versions/A/FinderKit (0x7fffa1eec3d8) and /System/Library/PrivateFrameworks/FileProvider.framework/OverrideBundles/FinderSyncCollaborationFileProviderOverride.bundle/Contents/MacOS/FinderSyncCollaborationFileProviderOverride (0x1f551f50). One of the two will be used. Which one is undefined.
ok
3>
Erlang doesn't have classes, so the class in question probably has something to do with "the viewer" software. According to this, it's an Apple issue.

io:getline(Prompt) in spawned process: Prompt does not display

Here's the code:
-module(my).
-compile(export_all).
test() ->
register(go, spawn(my, init, []) ).
init() ->
Reply = io:get_line("enter:"),
io:format("Reply= ~s~n", [Reply]).
In the shell:
~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
2> my:test().
true
3>
If I add a timer:sleep() here:
test() ->
register(go, spawn(my, init, []) ).
init() ->
timer:sleep(1000), %%<<<==========HERE
Reply = io:get_line("enter:"),
io:format("Reply= ~s~n", [Reply]).
and run the new code in the shell, then after 1 second the shell prompt 3> in the first example's output suddenly disappears and is replaced by enter::
~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
2> my:test().
true
enter:
And if I enter something, then as expected I see Reply= xx.
If I move the timer:sleep() to here:
test() ->
register(go, spawn(my, init, []) ),
timer:sleep(1000). %%<<======HERE
init() ->
Reply = io:get_line("enter:"),
io:format("Reply= ~s~n", [Reply]).
and I run the code in the shell, I see:
~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
2> my:test().
enter:
then enter: suddently disappears and is replaced by ok:
1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
2> my:test().
ok
3>
This does work as expected:
1> Reply = io:get_line("enter: ").
enter: hello
"hello\n"
2> Reply.
"hello\n"
3>
Can someone explain what race condition is occurring in the first example?
Actually this is not exactly race condition. The issue is raised from fact that we have only one std_in stream and only one process in given time can use it.
1) In first code snippet process 'go' takes control on std_in with get_line/1 function first. But after that test/0 function returns to Erlang shell and shell takes control under std_in (Erlang shell is waiting for user input with prompt like ">"). So process 'go' now unlinked from std_in and does not receive any chars from std_in. All input goes to Erlang shell.
2) Second snippet has sleep/1 function in init/1. So situation is opposite. We allow Erlang shell reach waiting for input status and AFTER that execute get_line/1 in 'go' process. So now 'go' process takes control on std_in and receives chars from keyboard. But after 'go' process terminates then Erlang shell restores its state.
3) Third snippet is just 1st but aggravate situation with sleep/1 function.
4) Nothing explain for forth snippet. It works as expected.
5) To illustrate this point of view you can run code below:
-module(my).
-compile(export_all).
test() ->
spawn_link(my, init1, []),
spawn_link(my, init2, []).
init1() ->
timer:sleep(100),
init(0, "0").
init2() ->
timer:sleep(100),
init(0, "1").
init(N, Title) ->
% io:format(">>init(~p)~n", [N]),
Reply = io:get_line(Title ++ "> enter:"),
io:format("[~s] (e - exit) Reply= ~s", [Title, Reply]),
case Reply of
"e\n" -> ok;
_ -> init(N+1, Title)
end.
The module starts two processes with get_line/1. But only one process can except input from std_in in recent moment:
50> my:test().
<0.192.0>
1> enter:w
[1] (e - exit) Reply= w
1> enter:d
[1] (e - exit) Reply= d
1> enter:e
[1] (e - exit) Reply= e
0> enter:dd
[0] (e - exit) Reply= dd
0> enter:e
[0] (e - exit) Reply= e
51>

Copying files from one server to other via erlang code

I want to copy files from one server(Say A) to other(Say B).Scenerio is->User sends me a file(video,zip or photo) in binary.I write this to /var/www/myfolder of A.Now in next step i want this to be copied at B.I used os:cmd(scp ----) command.But it gives error like->
Permission denied, please try again.
Permission denied, please try again.
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
I think it is asking for password of B.How can i configure password in scp command or is there any other method to do this in erlang?
You can use Erlang File I/O if you have both servers connected using erlang distribution protocol. (You can do it over TCP or UDP or any other networking as well but it is more complicated).
Let's demonstrate it using two "servers" running on the same machine (it works same over a network, but you have to connect them properly). First we make directory for each server and content of file foo to transfer:
$ mkdir a b
$ echo Hello World > a/foo
Let's start two servers each in a different directory:
$ cd a
a$ erl -sname a
Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V7.0 (abort with ^G)
(a#hynek-notebook)1>
and the second server in a different console:
$ cd b
b$ erl -sname b
Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V7.0 (abort with ^G)
(b#hynek-notebook)1>
Now we check there is nothing on the b server yet:
(b#hynek-notebook)1> ls().
ok
(b#hynek-notebook)2>
Now we can connect nodes, check if they are connected and read the file foo.
(a#hynek-notebook)1> net_kernel:connect('b#hynek-notebook').
true
(a#hynek-notebook)2> net_adm:ping('b#hynek-notebook').
pong
(a#hynek-notebook)3> ls().
foo
ok
(a#hynek-notebook)4> {ok, Bin} = file:read_file("foo").
{ok,<<"Hello World\n">>}
(a#hynek-notebook)5>
And write file to server b using rpc:call/4:
(a#hynek-notebook)5> rpc:call('b#hynek-notebook', file, write_file, ["bar", Bin]).
ok
(a#hynek-notebook)6>
Check the result on the server b:
(b#hynek-notebook)2> ls().
bar
ok
(b#hynek-notebook)3> {ok, Bin} = file:read_file("bar").
{ok,<<"Hello World\n">>}
(b#hynek-notebook)4>
For bigger files, you should not transfer a whole file in the one big binary. Unfortunately, you need at least some code support from sending or receiving side. You can transfer file handler from one node to another but the process which calls file:open/2 has to keep running. It is reason you can't just use {ok, FH} = rpc:call(Node, file, open, [FN, [write]]). It's a bummer. One way is to make a very simple server which opens a file and keeps running.
(b#hynek-notebook)4> Self = self().
<0.40.0>
(b#hynek-notebook)5> F = fun() -> Self ! file:open("baz", [write]), receive close -> ok end end.
#Fun<erl_eval.20.54118792>
(b#hynek-notebook)6> FS = spawn_link('a#hynek-notebook', F).
<7329.48.0>
(b#hynek-notebook)7> {ok, FH} = receive X -> X end.
{ok,<7329.49.0>}
(b#hynek-notebook)8> file:write(FH, Bin).
ok
(b#hynek-notebook)9> FS ! close.
close
(b#hynek-notebook)10>
And we expect file baz with proper content on the server a:
(a#hynek-notebook)6> ls().
baz foo
ok
(a#hynek-notebook)7> {ok, _} = file:read_file("baz").
{ok,<<"Hello World\n">>}
(a#hynek-notebook)8>
The other option is to write a server which will receive blocks and write them instead of sending a file handler. And there are many other options how to do it using direct TCP connection using HTTP or your own protocol and using file:send_file/2,5 and many other ways.

Why does net_kernel:monitor_nodes/2 not deliver nodeup/nodedown messages for sname nodes?

I start up a master node with a short name and get it running a process to monitor for node up and down messages.
> erl -sname master -cookie monster
Erlang R15B03 (erts-5.9.3) [source] [64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false] [dtrace]
Eshell V5.9.3 (abort with ^G)
(master#pencil)1> c("/tmp/monitor.erl").
{ok,monitor}
(master#pencil)2> Pid = monitor:start().
<0.44.0>
(master#pencil)3> Pid ! running.
RECV :: running
running
(master#pencil)4> net_adm:names().
{ok,[{"master",52564}]}
At this point only the master node is running. I startup the second node on the same machine:
> erl -sname client -cookie monster
Erlang R15B03 (erts-5.9.3) [source] [64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false] [dtrace]
Eshell V5.9.3 (abort with ^G)
(client#pencil)1>
and wait for a minute, just incase I'm reading the docs wrong and there's a complication with the net tickrate. Nothing, so on master I force the connection:
(master#pencil)5> net_adm:names().
{ok,[{"master",52564},{"client",52579}]}
(master#pencil)6>
and nothing from my little monitor process. Now, if I do the same thing but use long names--that is -name--this works just fine. I'm surprised, though, as the net_kernel docs don't mention that. What's the deal?
Here's the monitor.erl referenced above:
-module(monitor).
-export([start/0]).
start() ->
spawn_link(fun init_loop/0).
%%%===================================================================
%%% Internal Functions
%%%===================================================================
init_loop() ->
net_kernel:monitor_nodes(true, []),
loop().
loop() ->
receive
Msg -> io:format(user, "RECV :: ~p~n", [Msg])
end,
loop().
net_kernel:monitor_nodes/2 definitely does deliver nodeup/nodedown messages for nodes with either short and long names.
However, the nodeup message is only delivered when the node is connected, as mentioned in the documentation. Why you got the nodeup message with -name is a mystery (and couldn't be reproduced here) as net_adm:names/0 does not connect nodes at all. It only connects to epmd to obtain the list of locally registered nodes. It will even list nodes with a different cookie.
If you connect the client to the master (or the other way around) with net_adm:ping/1 (or an rpc call), the monitoring process will receive the nodeup message.

Erlang ping node problem

I made in erlang shell:
1> node().
nonode#nohost
But
2> net_adm:ping(node()).
pang
Why? What's problem? Why not pong?
Thank you.
You didn't start Erlang with -name or -sname, which means that the distribution subsystem was not started. Try this:
$ erl -sname mynode
Erlang R14B02 (erts-5.8.3) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.8.3 (abort with ^G)
(mynode#foobar)1> node().
mynode#foobar
(mynode#foobar)2> net_adm:ping(node()).
pong
I am not 100% sure, but You started erl without "-name" oder "-sname". I believe net_adm:ping/1 only works in a distributed mode.
If you are trying to ping an erlang node but getting a pang.
Check the cookie with erlang:get_cookie() it will be some random string set the cookie of another node with erlang:set_cookie(Node, Cookie) or you could pass the cookie to the flag -setcookie
for example:
(foo#earth) erlang:get_cookie().
ASYRQKVNIFHWIIJQZIYN
(foo#earth) erlang:set_cookie(node(), 'secret cookie').
true
net:ping('mongooseim#localhost').
pong
Check out the docs

Resources