Arc Forumnew | comments | leaders | submitlogin
How to run script using thread triggered from defop
2 points by thaddeus 5368 days ago | 3 comments
I have this function/process '(runjob)' that takes 2 or 3 minutes to run.

It runs fine from the toplevel.

If I try to initiate it with a defop as a thread the function bombs 9 or 10 seconds in to the process.

  (defopl doit req
    (let user (get-user req)
      (if (admin user)	
          (do (thread (runjob))
	      (prn "process excecuted!")))))

    

  Error...
  "display: output port is closed"
I thought I could get away with this given I threaded it, but apparently not. Any suggestions?


2 points by rocketnia 5367 days ago | link

I'm not very familiar with srv.arc and stuff yet, but it seems to me like your (runjob) thread is just outliving the lifetime of the socket-accept streams opened in srv.arc's handle-request-1. First of all, your defopl form registers its behavior in the srvops* table. Later, in handle-request-1, a socket is opened, and then handle-request-thread is called, which in turn calls the srvops* op, but in the context of a w/stdout to that socket. Your thread is created, your op returns, and handle-request-1 closes the socket streams. Then your thread continues to run, and I presume that it tries to display something, but that the output is directed to the output stream that was already closed.

I don't know your specific situation, but if this is a page the admin visits in order to trigger (runjob) on the server, then the output of runjob--if there is any--is probably for the benefit of the server logs rather than something intended to be shown on the "/doit" page itself, right? If so, then I bet you can just change (thread (runjob)) to (thread (w/stdout console-out* (runjob))) and add (= console-out* (stdout)) somewhere on the top level.

-----

2 points by conanite 5367 days ago | link

Can you post 'runjob? Or describe which output ports it uses? I don't know if or how scheme threads inherit stdout from parent threads, but if they do, and runjob calls disp/pr and family, that would explain the error - it might be fixable by wrapping (runjob) with w/stdout somehow ...

-----

1 point by thaddeus 5367 days ago | link

Thank you both!

With (run-job) I was iterating through items and displaying progress to stderr using 'prne'.

  (def prne args (w/stdout (stderr) (apply prn args)))

  example...
  (def run-job ()
     (each item (keys items)
        (process items.item)
        (prne item)))
I suppose I should have just removed the progress, but wrapping run-job in 'w/stdout' as suggested worked perfectly! (+ I plan change it to write to a log file instead).

... and thanks for the detailed explanation.

-----