I'm trying to understand the differences between spawn and spawn_link, but can't quite grasp what happens when the function the process executes ends.
defmodule SendAndDie do
def send_and_die(target) do
send(target, "Goodbye")
# Process.exit(self, :boom)
end
end
dying_process = spawn_link(SendAndDie, :send_and_die, [self])
:timer.sleep(500)
IO.puts("Dying process is alive: #{Process.alive?(dying_process)}")
receive do
msg -> IO.puts(msg)
end
I expected the main process to fail, as it linked to a process that clearly died before the end of the program. However, the "Goodbye" message is printed and then the program exits normally. Changing spawn_link to spawn have no effect.
When I uncomment the Process.exit in line 4 I do see the difference between spawn and spawn_link (the later stops the whole program while the former doesn't). But, the Process.exit is the last execution in the send_and_die function. Isn't the process going to exit anyway when the function ends?
From the erlang manual on processes
The default behaviour when a process receives an exit signal with an exit reason other than normal, is to terminate and in turn emit exit signals with the same exit reason to its linked processes.
When the initial function of the process returns it terminates with reason normal, so this default behaviour does not bring down the linked process.
Related
This might be a silly mistake from my side that I have overlooked but I'm fairly new to UVM and I tried tinkering with my code for a while before this. I'm trying to send in a stream of 8 bit data within a packet using Data valid stall protocol from my UVM driver to the DUT. I'm facing an issue with my input monitor not being able to pick up these transactions that are driven.
I have a while loop with a condition that the valid bit must be high and the stall bit should be low. As long as this condition holds good, the monitor needs to pick up the data byte and push into the queue. I know for a fact that the data is being picked up and pushed to a queue as I used $display statements along the way. The problem is arising once all the data bytes are received and the valid bit goes low. Ideally, this should cause the exit from the while loop but isn't doing so. Any help here would be appreciated. I have attached a snippet of the code below. Thanks in advance.
virtual task main_phase (uvm_phase phase);
$display("Run phase of input monitor");
collect_transfer();
endtask: main_phase
virtual task collect_transfer();
fork
forever begin
wait_for_valid_transaction_cycle();
create_and_populate_pkt();
broadcast_pkt();
#(iP0_vif.cb_iP0_MON);
end
join_none
endtask: collect_transfer
virtual task wait_for_valid_transaction_cycle();
wait(iP0_vif.cb_iP0_MON.ip_valid && ~iP0_vif.cb_iP0_MON.ip_stall);
endtask: wait_for_valid_transaction_cycle
virtual task create_and_populate_pkt();
pkt = Router_seq_item :: type_id :: create("pkt");
pkt.valid = iP0_vif.cb_iP0_MON.ip_valid;
pkt.sop = iP0_vif.cb_iP0_MON.ip_sop;
$display("before data collection");
while(iP0_vif.cb_iP0_MON.ip_valid === `HIGH && iP0_vif.cb_iP0_MON.ip_stall === `LOW) begin
$display("After checking for stall");
pkt.data = iP0_vif.cb_iP0_MON.ip_data;
$display(pkt.data);
pkt.data_q.push_front(pkt.data);
pkt.eop = iP0_vif.cb_iP0_MON.ip_eop;
$display("print check in input monitor # time = %0t", $time);
#(iP0_vif.cb_iP0_MON);
end
$display("before printing input packet from monitor");
Check_for_port_route_and_populate_packet_field(pkt);
print_packet(pkt);
endtask: create_and_populate_pkt
The $display statement "before printing input packet from monitor" is not being displayed.
HIGH is defined as a binary 1 and LOW is defined as a binary 0.
The output of the code in terms of display statements is as below.
before data collection
before checking for stall
After checking for stall
2
print check in input monitor # time = 105
before checking for stall
After checking for stall
1
print check in input monitor # time = 115
before checking for stall
After checking for stall
3
print check in input monitor # time = 125
It's possible that the main phase objection is being dropped elsewhere in your environment. UVM will automatically kill any threads that were spawned during a phase when it ends.
To fix this, do not object to the main phase in your monitor. Objecting to that phase is the responsibility of the threads creating the stimulus. Instead, you should be launching this monitor during the run_phase, which will ensure that your loop is not killed until the end of simulation.
Also, during the shutdown phase, you will want your monitor to object whenever it is currently seeing a packet. This will ensure that simulation doesn't end as soon as stimulus has been sent in, giving your other monitors time to collect responses from the DUT.
So I have a workflow which is supposed to throw an error after a certain condition is satisfied. (False condition) As you can see in the log directly below, it works: I do a loop exit first for the group 'coms' and an error is thrown. However, Flowgear seems to only read the last executed node and then determine the workflows status from that. Since the loop finishes last and is successful, if you look in the second log, you can see that the workflow has been evaluated as 'successful' although an error was thrown inside.
Any ideas how to make the loop break? Also why does flowgear only consider the last node? There should be an option in the error node to stop all execution.
Iterator nodes (Splitter and Loop) will consume the errors. The only way at this stage to get the workflow to return an error is to cause an error in the AnyError or UnhandledError part of the workflow. I've created a workflow to demonstrate this here: http://flowgear.me/s/UdpGBbd
Hope this helps.
If I were to have multiple batch files run one after another in VB.NET, would they run at the same time or would they wait for the first ones to finish before moving on the next?
They will run concurrently unless you go out of your way to prevent that from happening. Process.Start() does not block once the process has been launched. However, you can block by using Process.WaitForExit().
For example, this will run 3 batch files at the same time:
System.Diagnostics.Process.Start("batch.bat")
System.Diagnostics.Process.Start("batch.bat")
System.Diagnostics.Process.Start("batch.bat")
This will run them one at a time:
System.Diagnostics.Process.Start("batch.bat").WaitForExit()
System.Diagnostics.Process.Start("batch.bat").WaitForExit()
System.Diagnostics.Process.Start("batch.bat").WaitForExit()
You have more control over when the blocking takes place by saving the process to a variable and calling WaitForExit() later in the code:
Dim p1 = System.Diagnostics.Process.Start("batch.bat")
' Do stuff that doesn't need to wait for process to finish
p1.WaitForExit()
They will run together. If you want it to wait, create a ProcessStartInfo object, add it to the Process.Start call, and assign the Start method's response to a process. Then call the process's WaitForExit method.
I am testing my Delayed::Job using Rspec.
In my rspec_controller:
it "queues up delayed job and fires" do
setup
expect {
post :create, {:job => valid_attributes}
}.to change(Delayed::Job, :count).by(2)
Delayed::Worker.new.work_off.should == [2,0]
end
Delayed::Job.count passes as expected, but Delayed::Worker.new.work_off returns as [0,0], indicating there are 0 successes and 0 failures when there are 2 jobs.
How should I debug to find out why work_off doesn't fire the jobs.
Edit: The 2 jobs that are supposed to run, have their run_at set into the future. Does work_off fire off jobs that are not meant to be immediate?
Although this could be an older question, there's one parameter that's not much documented, try using
Delayed::Worker.new(quiet: false).work_off
to debug the result of your background jobs, this could help you to find out if the fact that they're supposed to run in the future is messing with the assert itself.
EDIT: Don't forget to take off the "quiet:false" when you're done, otherwise your tests will always output the results of the background jobs.
The construct
Delayed::Worker.new.work_off
immediately processes everything that is in the DJ queue, and in the same thread as the caller (it doesn't spawn a separate worker thread). But this doesn't explain why you're not getting [2, 0] for a result.
To answer your original question 'How should I debug to find out why work_off doesn't fire the jobs?', I suggest you use the callback hooks to trace the lifecycle of the jobs. Add a comment if you need to be shown how to do that... :)
I have erlang application. In this application i run process with spawn(?MODULE, my_foo, [my_param1, my_param2, my_param3]).
And my_foo:
my_foo(my_param1, my_param2, my_param3) ->
...
some code here
...
ok.
When i open etop i see that this my_foo/3 function status: proc_lib:sync_wait/2
Than i try to put exit(self(), normal) in the end of my function, but i see same behavior: proc_lib:sync_wait/2 in etop.
How can i kill or exit process correctly?
Thank you.
Note that exit(Pid, Reason) and exit(Reason) do NOT do the same thing if Pid is the process itself. exit/1 tells the current process to exit - from the inside if you like - while exit/2 sends an exit signal to the process, even if the process is itself. So when you do exit(self(), normal) you are actually sending the normal exit signal to yourself, which is ignored.
In this case putting the exit call at the end of the function should not make any difference as the process automatically dies (with reason normal) when the function with which it was started ends. It seems like the process is suspended somewhere before that.
proc_lib:sync_wait/2 is called inside proc_lib:start/start_link and sits and waits for the spawned process to do proc_lib:init_ack/1/2 to return the return value for start. It would appear that your process does not call init_ack.
Based on the limited information that you give in the question I would suspect that your process hasn't finished running yet.
Normally you don't need to add exit/2 to your process. It will exit automatically when the function has finished running.
You probably have a long running call in some code here that has not finished running. I recommend that you add logging information and see where you are stuck.