I have no idea either, very weird. I also tested to simply pass (1 2 3
4) and using your updatePresentFeed function, however I put (traceAll)
at the top of updatePresentFeeds, this is what I get:
task : -1000 (0 Pid NIL Cycles 0 Feeds Feeds (cond ((nand Pid (kill
Pid 0)) (if (pop 'Feeds) (setq Pid (or (fork) (updatePresentFeed @))
Cycles 30) (task -1000))) ((=3D0 (dec 'Cycles)) (and (kill Pid) (off
task =3D (-1000 0 (job '((Pid) (Cycles . 0) (Feeds 1 2 3 4)) (cond
((nand Pid (kill Pid 0)) (if (pop 'Feeds) (setq Pid (or (fork)
(updatePresentFeed @)) Cycles 30) (task -1000))) ((=3D0 (dec 'Cycles))
(and (kill Pid) (off Pid))))))
I suspect that the above will not help much.
Can you think of anything at all that might be interfering with the
task execution, for instance running two servers/tasks listening on
different ports at the same time in this very same parent?
On Sat, Sep 4, 2010 at 5:26 PM, Alexander Burger <a...@software-lab.de> wrot=
> Hi Henrik,
>> me. How exactly is (fork) working? The reference example:
>> (unless (fork) (do 5 (println 'OK) (wait 1000)) (bye))
>> seems to imply that the current expression, ie. (unless ... ) is being
>> rerun in the child (becoming the contents of *Fork) whilst execution
>> continues to the (bye) in the parent. The (fork) call will return NIL
>> in the child so the (do ... ) expression is being run there. It also
>> seems to imply that the (bye) expression waits for the child to finish
>> before shutting down?
> This description is not correct in some points.
> The PicoLisp 'fork' maps to the underlying fork() system call. When
> fork() is called, an new process is created, and both processes (the
> parent and the child) continue to execute from that point. At that
> moment, both processes are identical, the only difference is that in the
> parent process fork() returns the child's process ID, while in the child
> 0 is returned.
> The PicoLisp (fork) function returns a number (the child's PID) in the
> parent process, and NIL in the child process. So in the above example
> =A0 (unless (fork)
> is executed in the current process (which will be the "parent"
> thereafter), and (fork) returns the PID of the child. This is non-NIL,
> so the body of the 'unless' call is skipped by the parent, and it will
> continue execution with the next expression (not shown here).
> In the child process, (fork) returns NIL, and the body of the 'unless'
> call is executed. It consists of the two expressions
> =A0 (do 5 (println 'OK) (wait 1000))
> =A0 (bye)
> This is the code the child process sees. It prints five times 'OK' and
> then exits (terminating the child process).
> Note that the (bye) is probably important, because otherwise the child
> would continue with the next (not shown) expression which was already
> executed by the parent 5 seconds before.
> Thus, (unless (fork) (do-something) (bye)) is a typical pattern to have
> (do-something) done in a child process. In that regard, the formulation
> "(unless ..) is being rerun in the child" is a bit misleading, as the
> 'unless' is begins execution only in the parent, but after its condition
> (the (fork)) is evaluated, we suddenly have two processes which execute
> different branches in the code (the next statement in the parent, and
> the body of 'unless' in the child). That's the reason for the name of
> that system call, "fork".
> Then the formulation "(becoming the contents of *Fork)" is not correct.
> The global variable '*Fork' is not changed in that process, it may be
> set under program control _before_ the call to (fork) to contain
> expressions which should be executed in all child processes. Perhaps you
> meant '*Pid'? This is changed to a new value in the child process.
> Also, "whilst execution continues to the (bye) in the parent" is not
> right, as the parent never sees the (bye). It is only there for the
> child to terminate after it did its job.
>> Anyway, having a wait call like that as is the case in my code could
>> result in various race conditions, according to Alex he had to make
>> (wait) "smart" in order to avoid common cases, I'm sure he can
>> elaborate further on the details... In any case it works in my case
> Yes, though I would not say that there are race conditions.
> 'wait' is actually the PicoLisp "Event Handler". It can be called
> explicitly, and is called implicitly by other functions (see the
> reference of '*Run').
> This event handler takes care of several things, listening on file
> descriptors and watching timeout values. This includes all expressions
> in '*Run' (typically installed and de-installed by 'task'), but also
> internal events resulting from interprocess communication: The parent
> relays 'tell' messages from a child to all other children, accepts
> 'boss' commands (via 'hear'), detects when child processes terminate to
> clean up their resources, and is needed to synchronize the database
> between all child processes.
> So typically 'wait' processes a list of events. Now you may well call
> another 'wait' in a task, and this in fact happens frequently during
> database synchronization between child processes, or when GUI functions
> execute. However, 'wait' must ensure that while processing a list of
> events, a recursively called 'wait' does not re-execute the same event a
> second time. For that, the inner 'wait' takes care not to look at the
> events in the outer 'wait', and this may result that outer events will
> never get executed if the inner 'wait' is run in a loop in some task.
> Anyway, this may get rather confusing, and isn't the way 'task's are
> intended. I mean, instead that a task establishes its own timing loop
> using nested 'wait's, one central capability of tasks _is_ being a
> timer. That's why I recommended not to write such a loop in the task,
> but execute the checking for that child process periodically with.
>> but in order to avoid using (wait) Alex offered me the following
>> (de updatePresentFeeds (Feeds)
>> =A0 =A0(task -1000 0
>> =A0 =A0 =A0 Pid NIL
>> =A0 =A0 =A0 Cycles 0
>> =A0 =A0 =A0 Feeds Feeds
>> =A0 =A0 =A0 (cond
>> =A0 =A0 =A0 =A0 =A0((nand Pid (kill Pid 0))
>> =A0 =A0 =A0 =A0 =A0 =A0 (if (pop 'Feeds)
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(setq
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Pid (or (fork) (updatePresentFeed @)=
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Cycles 30 )
>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(task -1000) ) )
>> =A0 =A0 =A0 =A0 =A0((=3D0 (dec 'Cycles))
>> =A0 =A0 =A0 =A0 =A0 =A0 (and (kill Pid) (off Pid)) ) ) ) )
>> The main thing here is to initiate a task that is being run every
>> second, when all feeds have been imported we terminate through the
>> (task -1000) call. The first condition will be run initially (Pid is
> Correct. This will start a task which runs once a second, and has three
> local variables Pid, Cycles and Feeds (a closure).
>> The problem: It won't run at all, not even once and I have no idea
>> why, it all looks good to me.
> Strange. I cannot see at the moment what might be the problem.
> To test it locally, I tried the following, using a stub function for
> =A0 (de updatePresentFeed (F)
> =A0 =A0 =A0(msg F '<feed> *Pid)
> =A0 =A0 =A0(bye) )
> =A0 (de updatePresentFeeds (Feeds)
> =A0 =A0 =A0(task -1000 0
> =A0 =A0 =A0 =A0 Pid NIL
> =A0 =A0 =A0 =A0 Cycles 0
> =A0 =A0 =A0 =A0 Feeds Feeds
> =A0 =A0 =A0 =A0 (cond
> =A0 =A0 =A0 =A0 =A0 =A0((nand Pid (kill Pid 0))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 (if (pop 'Feeds)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(setq
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Pid (or (fork) (updatePresentFeed=
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Cycles 30 )
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0(task -1000) ) )
> =A0 =A0 =A0 =A0 =A0 =A0((=3D0 (dec 'Cycles))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 (and (kill Pid) (off Pid)) ) ) ) )
> =A0 (updatePresentFeeds (1 2 3 4))
> This seems to work, printing the numbers 1 .. 4 (the "feeds") and the
> PIDs of the individual child processes:
> =A0 1<feed>28662
> =A0 2<feed>28711
> =A0 3<feed>28763
> =A0 4<feed>28815
> What exactly goes wrong?
> - Alex
> UNSUBSCRIBE: mailto:picol...@software-lab.de?subject=3dunsubscribe