Re: [Chicken-users] Spiffy subprocess cleanup

2013-05-23 Thread Peter Bex
On Wed, May 22, 2013 at 10:29:03PM -0700, Evan Hanson wrote:
 After looking at a bit more, here's what I believe is *actually*
 happening:
 
 The invalid call to process* is signaling an exception in the child,
 which is handled internally by spiffy (spiffy.scm:470), causing that
 process to loop back to the start of the accept-next-connection
 procedure inside spiffy's accept-loop. At this point you have two
 processes listening on 8080, with the parent waiting for the child (who
 has no plans to exit). The same thing happens with each request, so the
 subprocesses pile up.

Thanks for the excellent debugging work.  I think process-fork really
needs to catch exceptions and exit instead of simply exiting if the
thunk returns normally.  Will post a patch later, unless someone beats
me to it.

Cheers,
Peter
-- 
http://www.more-magic.net

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] Spiffy subprocess cleanup

2013-05-23 Thread Bryan Vicknair
On Thu, May 23, 2013 at 09:14:25AM +0200, Peter Bex wrote:
 On Wed, May 22, 2013 at 10:29:03PM -0700, Evan Hanson wrote:
  After looking at a bit more, here's what I believe is *actually*
  happening:
  
  The invalid call to process* is signaling an exception in the child,
  which is handled internally by spiffy (spiffy.scm:470), causing that
  process to loop back to the start of the accept-next-connection
  procedure inside spiffy's accept-loop. At this point you have two
  processes listening on 8080, with the parent waiting for the child (who
  has no plans to exit). The same thing happens with each request, so the
  subprocesses pile up.
 
 Thanks for the excellent debugging work.  I think process-fork really
 needs to catch exceptions and exit instead of simply exiting if the
 thunk returns normally.  Will post a patch later, unless someone beats
 me to it.
 
 Cheers,
 Peter

Thanks a lot Evan and Peter.  That was very helpful.

I started looking at the process-fork source to write a patch, but I'm not
familiar enough with chicken-core yet to tackle it.  For now I changed my code
to use the process* variant that sends a command to the shell and that is
working.

One step closer to using chicken/spiffy for new web development at my company.
Wrapping up the first version of an egg to get at multipart/form-data in
spiffy so I can accept file uploads.


Bryan

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] Spiffy subprocess cleanup

2013-05-23 Thread Peter Bex
On Thu, May 23, 2013 at 08:57:09AM -0700, Bryan Vicknair wrote:
 Thanks a lot Evan and Peter.  That was very helpful.
 
 I started looking at the process-fork source to write a patch, but I'm not
 familiar enough with chicken-core yet to tackle it.  For now I changed my code
 to use the process* variant that sends a command to the shell and that is
 working.

I've attached a patch that I *think* does the trick.  It also shoots down
any additional threads which may be running in the child process
(even though those should probably not get a chance to run, you never know).
I've also simplified the argument handling and needless(?) messing about
with process-fork without thunk in process-run.

I'd love it if people could test this and provide feedback, because I'm
pretty unsure whether this fix is the correct one.  I've had some trouble
trying to wait for the process, but I was unable to do that even if the
program I tried to execute existed, so that must be a case of PEBKAC.

Cheers,
Peter
-- 
http://www.more-magic.net
From d4de7eb646e57e8c2d2e3d3649cf1a3ec1b65cd8 Mon Sep 17 00:00:00 2001
From: Peter Bex peter@xs4all.nl
Date: Thu, 23 May 2013 21:15:19 +0200
Subject: [PATCH] Kill other threads when starting a process, and exit even
 when an exception occurs (reported by Bryan Vicknair, analysis by Evan
 Hanson)

---
 NEWS  |  3 +++
 posixunix.scm | 32 ++--
 2 files changed, 21 insertions(+), 14 deletions(-)

diff --git a/NEWS b/NEWS
index be9d098..c08ca60 100644
--- a/NEWS
+++ b/NEWS
@@ -32,6 +32,9 @@
  (thanks to Florian Zumbiehl)
   - posix: memory-mapped file support for Windows (thanks to rivo)
   - posix: find-file's test argument now also accepts SRE forms.
+  - posix: process, process* and process-run now properly kill other threads
+ and cause the process to exit with status 1 if running the process fails
+ (thanks to Evan Hanson and Bryan Vicknair)
 
 - Runtime system
   - Special events in poll() are now handled, avoiding hangs in threaded apps.
diff --git a/posixunix.scm b/posixunix.scm
index a2776da..7d8dcaf 100644
--- a/posixunix.scm
+++ b/posixunix.scm
@@ -1734,12 +1734,14 @@ EOF
(when (fx= -1 pid) 
  (posix-error #:process-error 'process-fork cannot create child 
process))
(if (and thunk (zero? pid))
-   ((if killothers
-##sys#kill-other-threads
-(lambda (thunk) (thunk)))
-(lambda ()
-  (thunk)
-  ((foreign-lambda void _exit int) 0) ))
+   (handle-exceptions exn
+   ((foreign-lambda void _exit int) 1)
+   ((if killothers
+##sys#kill-other-threads
+(lambda (thunk) (thunk)))
+(lambda ()
+  (thunk)
+  ((foreign-lambda void _exit int) 0) )))
pid)
 
 (define process-execute
@@ -1816,13 +1818,14 @@ EOF
   (list -c cmdlin) )
 
 (define process-run
-  (lambda (f . args)
-(let ([args (if (pair? args) (car args) #f)]
- [pid (process-fork)] )
-  (cond [(not (eq? 0 pid)) pid]
-   [args (process-execute f args)]
-   [else
-(process-execute (##sys#shell-command) 
(##sys#shell-command-arguments f)) ] ) ) ) )
+  (lambda (f #!optional args)
+(process-fork
+ (lambda ()
+   (if args
+   (process-execute f args)
+   (process-execute (##sys#shell-command)
+(##sys#shell-command-arguments f)) ))
+ #t)  ) )
 
 ;;; Run subprocess connected with pipes:
 
@@ -1893,7 +1896,8 @@ EOF
 (connect-child loc opipe stdinf fileno/stdin)
 (connect-child loc (swapped-ends ipipe) stdoutf 
fileno/stdout)
 (connect-child loc (swapped-ends epipe) stderrf 
fileno/stderr)
-(process-execute cmd args env ) ) )]
+(process-execute cmd args env))
+  #t)) ) ) )]
   [input-port
 (lambda (loc pid cmd pipe stdf stdfd on-close)
   (and-let* ([fd (connect-parent loc pipe stdf stdfd)])
-- 
1.8.2.3

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


[Chicken-users] Spiffy subprocess cleanup

2013-05-22 Thread Bryan Vicknair
I have a web app using spiffy that uses (process*) in one of the views to wait
on a script to do some work.  I was accidentally passing in a non-existent
script name to process*, which was causing a 500 code to be returned by
spiffy. 

The problem is that there is no indication of any error sent to stderr/stdout
by spiffy.  Also, each time I visit the broken view's URL, a new subprocess is
created and never killed.

Here is an example:

  (use posix spiffy)
  
  (define (fail)
(define-values (i o pid e) (process* non-existant '(arg1 arg2)))
(close-output-port o)
(close-input-port i)
(close-input-port e))
  
  
  (define (server arg)
(print starting subprocess...)
(fail)
(send-status ok done))
  
  (access-log (current-output-port))
  (error-log (current-error-port))
  (debug-log (current-output-port))
  (handle-not-found server)
  (root-path ./)
  (start-server)



If you save the above code in foo.scm, compile and run it, then go to
http://localhost:8080/bla a few times so the handle-not-found handler is
called, you'll get a 500 error.  But the shell you started foo in won't show
any details on the error.  If you look at pstree, you'll see that there are
subprocesses hanging around: sh--bash--foo-foo-foo-foo

I thought there might be strange interplay between the thread that spiffy is
using to serve the view and the (process*) call.  The example below doesn't
involve spiffy, it just starts a thread that will fail by calling (process*)
with a non-existent script name:

  (use srfi-18 posix)


  (define (fail)
(define-values (i o pid e) (process* non-existant '(arg1 arg2)))
(close-output-port o)
(close-input-port i)
(close-input-port e))


  (print staring thread that will fail)
  (thread-start! (make-thread (lambda()
(thread-sleep! 1)
(fail

  (thread-sleep! 2)
  (print main thread done)

This works as expected however.  There are no subprocesses lying around, and
the error appears on stderr.

Does anyone understand why the (process*) call in the spiffy example doesn't
show an error on stderr/stdout and leaves subprocesses alive?


Bryan

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] Spiffy subprocess cleanup

2013-05-22 Thread Evan Hanson
Hi Bryan,

I tried to paste a response but missed you in #chicken. I think you need
to make sure to close the ports returned by process* (in your paste, the
close-input/output-port forms aren't running since process* is signaling
an error):

http://paste.call-cc.org/paste?id=76432a008b2c4310d0044e91d4bcf48c74b730d8#a1

You can register an exception handler for spiffy to make it more clear
what/when things are going wrong:

http://api.call-cc.org/doc/spiffy#def:handle-exception

Cheers,

Evan

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users


Re: [Chicken-users] Spiffy subprocess cleanup

2013-05-22 Thread Evan Hanson
After looking at a bit more, here's what I believe is *actually*
happening:

The invalid call to process* is signaling an exception in the child,
which is handled internally by spiffy (spiffy.scm:470), causing that
process to loop back to the start of the accept-next-connection
procedure inside spiffy's accept-loop. At this point you have two
processes listening on 8080, with the parent waiting for the child (who
has no plans to exit). The same thing happens with each request, so the
subprocesses pile up.

Evan

___
Chicken-users mailing list
Chicken-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/chicken-users