I have the following Erlang code running on Eclipse Erlide:
%% #author gakuo
%% #doc #todo Add description to links.
-module(links).
%% ====================================================================
%% API functions
%% ====================================================================
-export([start/1, test/1,middle/2]).
%% ====================================================================
%% Internal functions
%% ====================================================================
start(N)->
register(first,spawn_link(links,make,[N-1])).
make(0)->
last();
make(N)->
middle(spawn_link(links,make,[N-1]),N).
middle(Next,N)->
receive
Msg->
Next ! Msg,
io:format("Process ~w received ~w~n",[N,Msg]),
middle(Next,N)
end.
last()->
receive
stop->
io:format("last process now exiting ~n", []),
exit(finished);
Msg->
io:format("last process received ~w ~n", [Msg]),
last()
end.
test(Msg)->
first ! Msg.
I run it as follows:
links:start(3).
At this point, I get the following error:
Eshell V9.0.4
(processlinking#GAKUO)1> links:start(3).
** exception exit: undef
in function links:make/1
called as links:make(2)
This happens before I run the next command which is:
links:test(stop).
After the two commands, I was expecting the following:
Process 2 received stop
Process 1 received stop
Last process now exiting
stop
After some research, I found out that Undef is raised because the function cannot be found when evaluating a function call. Further research on StackOverflow for similar errors did not help. The solutions involved upgrading the installed Erlang version but my problem seems to be a logical one. Being new to Erlang, I cannot point out what it is. As usual, your help will be highly appreciated.
spawn_link (and other functions that accept a module name + function name + arguments list) can only call functions that that module exports. Functions that are not exported are only callable from within the module and need to be called without the module name prefix. So, you need to export make/1 to make this code work:
-export([start/1, test/1, middle/2, make/1]).
^^^^^^
Related
I'm working on a TCL project, for which version control is based on Git. So, in order to produce good-quality code, I set up put execution of the tests in pre-commit hook.
However, even if they are executed (trace is shown in command-line), and one of the tests is failed, Git performs the commit. So I launched the hook manually to check the error code, and I figured out that it is null, explaining why Git does not stop:
$ .git/hooks/pre-commit
++++ FlattenResult-test PASSED
(...)
==== CheckF69F70 FAILED
==== Content of test case:
(...)
==== CheckF69F70 FAILED
$ echo $?
0
(Launching the tests script with tclsh also results in $? to be 0.)
So my question is about this last line: why is $? equal to 0, when one of the tcl tests is failed? And how can I achieve a simple pre-commit hook that stops on failure?
I read and reread the tcltest documentation, but saw no setting or information about this error code. And I would really like not to have to parse the tcl tests output, to check if ERROR or FAILED is present...
Edit: versions
TCL version : 8.5
tcltest version: 2.3.4
This depends on how you run your test suite. Normally you run a file called tests/all.tcl which may look something like this:
package require Tcl 8.6
package require tcltest 2.5
namespace import tcltest::*
configure -testdir [file dirname [file normalize [info script]]] {*}$argv
runAllTests
That final runAllTests returns a boolean indicating success (0) or failure (1). You can use that to generate an exit code by changing the last line to:
exit [runAllTests]
I use this redefinition in some of my test scripts:
# Exit non-zero if any tests fail.
# tcltest's `cleanupTests` resets the numTests array, so capture it first.
proc cleanupTests {} {
set failed [expr {$::tcltest::numTests(Failed) > 0}]
uplevel 1 ::tcltest::cleanupTests
if {$failed} then {exit 1}
}
After some research, I could make it work, even though several factors were against me:
I have to use an old TCL version (8.5) with tcltest version 2.3.4, in which runAllTests returns nothing;
I forgot to write cleanupTests at the end of test scripts, as the documentation is not really clear about its usage. (It is not clearer now. I just figured out it is needed if you want to get your tests run by runAllTests, which is really not obvious).
And here is my solution, mostly based on Hai's DevBits blog post:
all.tcl
package require tcltest
::tcltest::configure (...)
proc ::tcltest::cleanupTestsHook {} {
variable numTests
set ::exitCode [expr {$numTests(Total) == 0 || $numTests(Failed) > 0}]
}
::tcltest::runAllTests
exit $exitCode
Some thoughts about it:
I added $numTests(Total) == 0 as a failure condition: this means that no tests was found, which is clearly an erroneous condition;
This doesn't catch exceptions in the configuration of the tests, for instance a source command that points to a non-existing file, revealing some failure in tests scaffolding. This would be catched as error in other test framewords (ah, pytest, I miss you!)
I get the feeling this is one of those really simple problems where there's something I just don't understand about the language. But I'm trying to learn Elixir, and my program isn't running all the way through. I've got a minimal example here.
defmodule Foo do
def run(0) do
IO.puts("0")
end
def run(n) do
IO.puts(to_string n)
run(n - 1)
end
def go do
run(100)
end
end
# Foo.go
# spawn &Foo.go/0
Now, if I uncomment the Foo.go line at the bottom and run it with elixir minimal.exs, then I get the intended output, which is all of the numbers from 100 down to 0. If I uncomment only the spawn &Foo.go/0 line, I consistently get no output at all.
However, if I uncomment both lines and run the program, I get the numbers from 100 to 0 (from the first line), then the first few numbers (usually about 100 to 96 or so) before the program terminates for some reason. So I really don't know what's causing the process to terminate at a random point.
It's worth pointing out that the reason this confusion arose for me was that I was trying to use mix to compile a larger project, when the program seemed to get started, do a small part of its work, and then terminate because mix apparently stops running after a bit. So I'm not sure what the idiomatic way to run an Elixir program is either, given that mix seems to terminate it after a short while anyway.
spawn/1 will create a new process to run the function. While they are not the same, you can sort of think of an Erlang / Elixir process as a thread in most other languages.
So, when you start your program, the "main" process gets to doing some work. In your case, it creates a new process (lets call it "Process A") to output the numbers from 100 down to 0. However, the problem is that spawn/1 does not block. Meaning that the "main" process will keep executing and not wait for "Process A" to return.
So what is happening is that your "main" process is completing execution which ends the entire program. This is normal for every language I have ever used.
If you wanted to spawn some work in a different process and make sure it finishes execution BEFORE ending your program, you have a couple different options.
You could use the Task module. Something along the lines of this should work.
task = Task.async(&Foo.go/0)
Task.await(task)
You could explicitly send and receive messages
defmodule Foo do
def run(0, pid) do
IO.puts("0")
# This will send the message back to the "main" thread upon completion.
send pid, {:done, self()}
end
def run(n, pid) do
IO.puts(to_string n)
run(n - 1, pid)
end
# We now pass along the pid of the "main" thread into the go function.
def go(pid) do
run(100, pid)
end
end
# Use spawn/3 instead so we can pass in the "main" process pid.
pid = spawn(Foo, :go, [self()])
# This will block until it receives a message matching this pattern.
receive do
# The ^ is the pin operator. It ensures that we match against the same pid as before.
{:done, ^pid} -> :done
end
There are other ways of achieving this. Unfortunately, without knowing more about the problem you are trying to solve, I can only make basic suggestions.
With all of that said, mix will not arbitrarily stop your running program. For whatever reason, the "main" process must have finished execution. Also mix is a build tool, not really the way you should be running your application (though, you can). Again, without knowing what you are attempting to do or seeing your code, I cannot give you anything more than this.
I am trying to replicate the ventilator/workers/sink paradigm described in the ZMQ guide. I have the same Python Ventilator, the same C++ worker as, and the same Python Sink as was described in the ZMQ examples. I want to launch the ventilator, workers, and sink from one main python script, so I created "class" wrappers around the ventilator & sink, and both of those classes subclass the Python module "multiprocessing.Process." Since the C++ is a binary, I launch it with Python's subprocess.Popen call.
The order of starting all of this up is as follows:
h = subprocess.Popen('test') # test is the name of the binary
time.sleep(1)
s = sinkObj.start()
time.sleep(1)
v = ventObj.start()
What I am finding is that no data is getting through the system when I start up the components like this. However, if I start the C++ binary in its own shell, and only start the sinkObj and ventObj from the main python script, it works fine.
I apologize in advance if this is more of a Python question than a ZMQ question, but I haven't run into issues like this w/ Python's subprocess. I have also tried using os.system() instead of the subprocess... but same issue. I put all the code on this website: https://github.com/kkarrancsu/zmqtest if anybody is curious to test it out. There is a readme on that git which tells you what the files are.
Any ideas on why this could be happening?
------------------------- UPDATE --------------------
I found that if I create a shell script which simply launches the C binary, and call that shell script w/ os.system('run_the_shell_script') it works! So this means that there is something wrong with the way that I am using subprocess.Popen(...), but can't seem to pinpoint what the issue is. I tried w/ the shell=True flag, but it still hangs with that...
It's the name of the worker binary file that causes the problem.
There two solutions:
Chang the name of the binary file test to test_new and do the same in your All.py file, and then it will work as you desire.
Substitute subprocess.Popen('./test', shell=True) for subprocess.Popen('test', shell=True).
test is Linux command. If you type the following in your shell
$ echo $PATH
You may see that . is at the last position. It means that until shell couldn't find the binary file to be executed in the directories that $PATH indicates, it will try to search for it in the current directory .
When you execute subprocess.Popen('test', shell=True), it could find it before trying the . directory and so it won't execute the workers.
As I see, the ventilator and sink bind() to ports 6557 and 6558, and the C++ app connect() to these ports. In this case, if you start the cpp app first, it will try to connect() to the endpoints, but as nothing is bound there, it will drop silently.
In ZeroMQ the basic principle is "First Bind, then Connect". So you should not connect() before you bind() something on the socket. Imagine bind() is the 'Server', and connect() is the client. You cannot connect client to non-existing server. Also, in ZeroMQ every socket can be 'Server', but you SHOULD HAVE only 1 bind()-ing socket per URL. And you can have multiple 'connect()'s.
I am trying out several gradle basics.
Here is how my gradle file "build.gradle" looked:
task hello
{
doLast
{
println 'Hello World!'
}
}
This causes the following error:
D:\DevAreas\learn-gradle>gradle -q hello
FAILURE: Build failed with an exception.
* Where:
Build file 'D:\DevAreas\learn-gradle\build.gradle' line: 2
* What went wrong:
Could not compile build file 'D:\DevAreas\learn-gradle\build.gradle'.
> startup failed:
build file 'D:\DevAreas\learn-gradle\build.gradle': 2: Ambiguous expression could be a parameterle
ss closure expression, an isolated open code block, or it may continue a previous statement;
solution: Add an explicit parameter list, e.g. {it -> ...}, or force it to be treated as an open
block by giving it a label, e.g. L:{...}, and also either remove the previous newline, or add an exp
licit semicolon ';' # line 2, column 1.
{
^
1 error
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more l
og output.
If I make a minor modification to the build file like so
[Please NOTE that I have moved the parenthesis from second line to
first line]
task hello{
doLast
{
println 'Hello World!'
}
}
I see the output
Hello World!
with out issues.
Is parenthesis such a big problem in gradle? What was I doing so wrong by placing the parenthesis in the second line?
As with other languages that use semicolon inference, the newline makes a difference in Groovy. The first snippet gets parsed as task hello; { ... }, which is ambiguous (can't decide if the second statement is a block or a closure) and hence invalid Groovy syntax. It's not what you want anyway; you want the closure to be associated with the hello task. To avoid such surprises, I recommend to follow the Java braces style.
Long story short I am trying to replicate the Sleeping barber problem in Erlang.
In my solution I decided that for all the processes that are waiting I would put them into a list. Then, once it was that processes turn, I would take that PID off of the list.
Unfortunately when I call
length(myListOfPids).
it fails, as an example:
length([<0.46.0>]).
* 2: syntax error before: '<'
is there a way to store PID's so that I can recall them and use them normally? i.e.
PID ! message
... just in case it matters here is the actual error I recieve when running my program:
=ERROR REPORT==== 1-Jul-2010::05:50:40 ===
Error in process <0.44.0> with exit value:
{badarg,[{erlang,length,[<0.46.0>]},{barber1,waitingRoom,2}]}
barber1 is my module, waitingRoom is the function that keeps track of which processes are waiting
You can also construct a Pid from it's three components using pid/3.
1> length([pid(0,35,0)]).
Be aware that using any of these techniques for constructing Pid goes wrong if you construct a pid on a different node than the one it was created on.
The problem your program is having is different.
{badarg,[{erlang,length,[<0.46.0>]},{barber1,waitingRoom,2}]}
A call to erlang:length/1 created a badarg. The third element of {erlang,length,[<0.46.0>]} is the list of arguments passed to erlang:length. So that's equivalent to:
1> erlang:length(pid(0,46,0)).
where you intended:
1> erlang:length([pid(0,46,0)]).
(Annoyingly, the erlang shell now hides erlang's internal representation of errors from you. Replacing the above error with:
** exception error: bad argument in function length/1 called as length(<0.35.0>)
which is much easier to understand but less useful because it gets in the way of learning the essential skill of interpreting erlang errors yourself.)
Entering Pids by typing them does not work for me either.
Is that the only problem?
With code:
-module(test).
-export([loop/0]).
loop() ->
receive
{hello} ->
io:format("Hello world!~n"),
loop()
end.
I get:
Eshell V5.7.5 (abort with ^G)
1> Pid = spawn(fun test:loop/0).
<0.35.0>
2> L = [Pid].
[<0.35.0>]
3> length(L).
1
This error message:
=ERROR REPORT==== 1-Jul-2010::05:50:40 ===
Error in process <0.44.0> with exit value:
{badarg,[{erlang,length,[<0.46.0>]},{barber1,waitingRoom,2}]}
means that you were calling length(<0.46.0>), not length([<0.46.0>]) (ignoring for the moment that PIDs can only be written, not read). In the stack trace the topmost function will have the list of arguments. Since length takes one argument, this list has a single argument: you are taking the length of a PID, which obviously fails, since only lists have lengths.
The problem is that while <0.46.0> is the way that a PID gets printed, it can't be entered this way. You can use list_to_pid("<0.46.0>") instead. Of course, once you do have a PID (created in this way, returned from spawn, etc.), it can be stored in a list and retrieved like any other Erlang term.
The standard way to get a pid is to take the return value of a spawn function, either spawn/1, spawn/3, spawn_link/1, spawn_link/3, and the proc_lib equivalents.
A simple way to write down a pid is with the function c:pid/3, called like c:pid(0,25,0), which will return <0.25.0>. That's a shortcut function for the shell. Otherwise, you can use list_to_pid/1 as mentioned by Alexey Romanov.
However, you should be aware of the role of pids before trying to build them by hand. The pid acts as the personal identifier of a process and is meant to be used only by those who know about it. If you don't have the pid in your hand already, then you likely shouldn't be in its possession already. Indirectly, this is meant to lead to insulation of different parts of a program — only care about those bits that you spawned and have each part of your program mind its own business.
The cleanest way to do it is thus to use the return value of a spawn function. Generating a pid by hand should be left as a debugging solution only.