Commits

evhan committed 3d532f1

Single dispatcher, stop & wait, join fuse threads, exit fuse_loop on OpenBSD

Comments (0)

Files changed (2)

 
 (module fuse
   (make-filesystem
-   start-filesystem
-   stop-filesystem
+   filesystem-start!
+   filesystem-stop!
    filesystem-running?
+   filesystem-wait!
    filesystem?
    file/fifo
    file/chr
 (define-foreign-type fuse_fill_dir_t
   (function int (c-pointer c-string (c-pointer (struct "stat")) off_t)))
 
+(define-inline (true) #t)
 (define-inline (false) #f)
 
 (define-inline (vector-for-each f v) ; . v
        (callback-result v)))))
 
 (define-callback (init (c-pointer data)) c-pointer
+  (mount-running-handler-set! (current-mount) true)
   (callback-protect (current-filesystem-callback 21))
   (fuse_context_private_data current-fuse-context))
 
-;(define-callback (destroy (c-pointer data)) void
-;  (callback-protect (current-filesystem-callback 22)))
+(define-callback (destroy (c-pointer data)) void
+  (callback-protect (current-filesystem-callback 22)))
 
 (define make-gc-root
   (foreign-primitive c-pointer ((scheme-object obj))
   sigaddset(&s, SIGTERM);
   pthread_sigmask(SIG_BLOCK, &s, NULL);
   fuse_loop_mt(fuse);
-  fuse_exit(fuse);
   return NULL;
 }
 
-long start_fuse_thread(void *fuse) {
-  pthread_t t;
-  if (pthread_create(&t, NULL, fuse_loop_worker, fuse))
-    C_return(0);
+void *start_fuse_thread(void *fuse) {
+  pthread_t *thread = malloc(sizeof(pthread_t));
+  if (NULL == thread)
+    C_return(NULL);
+  if (pthread_create(thread, NULL, fuse_loop_worker, fuse))
+    C_return(NULL);
   else
-    C_return((long) t);
+    C_return(thread);
+}
+
+int stop_fuse_thread(pthread_t *thread) {
+  int result = 0;
+  if (pthread_cancel(*thread))
+    goto out;
+  if (pthread_join(*thread, NULL))
+    goto out;
+  else
+    result = 1;
+out:
+  free(thread);
+  C_return(result);
 }
 
 <#
 
-(define (start-fuse-thread! fuse)
-  (when (zero? ((foreign-lambda long start_fuse_thread c-pointer) fuse))
-    (error 'start-filesystem "couldn't start FUSE thread")))
+(define start-fuse-thread!
+  (foreign-lambda c-pointer start_fuse_thread c-pointer))
+
+(define stop-fuse-thread!
+  (cond-expand
+    (openbsd (foreign-lambda bool stop_fuse_thread c-pointer))
+    (else void)))
 
-(define start-filesystem
+(define filesystem-start!
   (let* ((opsize (foreign-type-size "struct fuse_operations"))
          (ops    (allocate opsize)))
     (fuse_operations_getattr_set!  ops (foreign-value "fuse_getattr_callback" c-pointer))
     (fuse_operations_statfs_set!   ops (foreign-value "fuse_statfs_callback" c-pointer))
     (fuse_operations_init_set!     ops (foreign-value "fuse_init_callback" c-pointer))
     (lambda (path fs)
-      (and-let* ((chan  (fuse_mount path #f))
-                 (mount (make-mount fs false void (current-exception-handler)))
-                 (root  (make-gc-root mount))
-                 (fuse  (fuse_new chan #f ops opsize root)))
-        (handle-exceptions e
-          (begin
-            (stop-filesystem path fs)
-            (unless (join-timeout-exception? e) (raise e)))
-          (let ((d (gensym "dispatcher")))
-            (start-fuse-thread! fuse)
-            (filesystem-mount-add! fs path mount)
-            (on-exit (lambda () (stop-filesystem path fs)))
-            (mount-running-handler-set!
-             mount
-             (lambda ()
-               (not (fuse_exited fuse))))
-            (mount-shutdown-handler-set!
-             mount
-             (lambda ()
-               (dispatcher-terminate! (dispatcher d))
-               (mount-running-handler-set! mount false)
-               (mount-shutdown-handler-set! mount void)
-               (filesystem-mount-delete! fs path)
-               (fuse_exit fuse)
-               (fuse_unmount path chan)
-               (fuse_destroy fuse)
-               (gc-root-destroy! root)
-               (let ((destroy-callback
-                      (##sys#vector-ref (filesystem-operations fs) 22)))
-                 (when destroy-callback (destroy-callback)))))
-            (dispatch d)))))))
-
-(define (stop-filesystem path fs)
+      (and-let* ((chan   (fuse_mount path #f))
+                 (mount  (make-mount fs false void (current-exception-handler)))
+                 (root   (make-gc-root mount))
+                 (fuse   (fuse_new chan #f ops opsize root))
+                 (thread (start-fuse-thread! fuse)))
+        (filesystem-mount-add! fs path mount)
+        (mount-shutdown-handler-set!
+         mount
+         (lambda ()
+           (mount-shutdown-handler-set! mount false)
+           (cond-expand
+             (openbsd (fuse_destroy fuse))
+             (else (fuse_exit fuse)))
+           (fuse_unmount path chan)
+           (stop-fuse-thread! thread)
+           (mount-running-handler-set! mount false)
+           (filesystem-mount-delete! fs path)
+           (cond-expand
+             (openbsd)
+             (else (fuse_destroy fuse)))
+           (gc-root-destroy! root)
+           (let ((destroy-callback
+                  (##sys#vector-ref (filesystem-operations fs) 22)))
+             (when destroy-callback (destroy-callback)))))
+        (filesystem-wait! path fs values)))))
+
+;; TODO Proper synchronization.
+(define (filesystem-wait! path fs #!optional (test not))
+  (do () ((test (filesystem-running? path fs))) (thread-sleep! 0.1)))
+
+(define (filesystem-stop! path fs)
   (and-let* ((mount (alist-ref path (filesystem-mounts fs) string=?)))
     ((mount-shutdown-handler mount))))
 
     ; #;fuse_operations_flock_set!))
 
   (define fuse_new (foreign-lambda fuse fuse_new fuse_chan fuse_args (const fuse_operations) size_t c-pointer))
-  (define fuse_destroy (foreign-safe-lambda void fuse_destroy fuse))
-  (define fuse_loop (foreign-safe-lambda int fuse_loop fuse))
+  (define fuse_destroy (foreign-lambda void fuse_destroy fuse))
+  (define fuse_loop (foreign-lambda int fuse_loop fuse))
   (define fuse_get_context (foreign-lambda fuse_context fuse_get_context))
   (define fuse_get_session (foreign-lambda fuse_session fuse_get_session fuse))
   ;(define fuse_getgroups (foreign-lambda int fuse_getgroups int (c-pointer gid_t)))
   ;(define fuse_version (foreign-lambda int fuse_version))
   ;(define fuse_pollhandle_destroy (foreign-lambda void fuse_pollhandle_destroy fuse_pollhandle))
 
-  (define fuse_loop_mt (foreign-safe-lambda int fuse_loop_mt fuse))
+  (define fuse_loop_mt (foreign-lambda int fuse_loop_mt fuse))
   ;(define fuse_start_cleanup_thread (foreign-lambda int fuse_start_cleanup_thread fuse))
   ;(define fuse_start_cleanup_thread (foreign-lambda void fuse_stop_cleanup_thread fuse))
   ;(define fuse_clean_cache (foreign-lambda int fuse_clean_cache fuse))
   ;(define fuse_session_add_chan (foreign-lambda void fuse_session_add_chan fuse_session fuse_chan))
   ;(define fuse_session_remove_chan (foreign-lambda void fuse_session_remove_chan fuse_chan))
   ;(define fuse_session_next_chan (foreign-lambda fuse_chan fuse_session_next_chan fuse_session fuse_chan))
-  ;(define fuse_session_process (foreign-safe-lambda void fuse_session_process fuse_session c-pointer size_t fuse_chan))
+  ;(define fuse_session_process (foreign-lambda void fuse_session_process fuse_session c-pointer size_t fuse_chan))
   ;(define fuse_session_process_buf (foreign-lambda void fuse_session_process_buf fuse_session (const fuse_buf) fuse_chan))
   ;(define fuse_session_receive_buf (foreign-lambda int fuse_session_receive_buf fuse_session fuse_buf (c-pointer fuse_chan)))
   ;(define fuse_session_destroy (foreign-lambda void fuse_session_destroy fuse_session))
   ;(define fuse_session_reset (foreign-lambda void fuse_session_reset fuse_session))
   ;(define fuse_session_exited (foreign-lambda bool fuse_session_exited fuse_session))
   ;(define fuse_session_data (foreign-lambda c-pointer fuse_session_data fuse_session))
-  ;(define fuse_session_loop (foreign-safe-lambda int fuse_session_loop fuse_session))
+  ;(define fuse_session_loop (foreign-lambda int fuse_session_loop fuse_session))
 
   ;; fuse_main is defined as a macro.
   (define (fuse_main argc argv op user_data)
-    ((foreign-safe-lambda* int ((int argc)
-                                ((c-pointer c-string) argv)
-                                (fuse_operations op)
-                                (c-pointer user_data))
+    ((foreign-lambda* int ((int argc)
+                           ((c-pointer c-string) argv)
+                           (fuse_operations op)
+                           (c-pointer user_data))
       "C_return(fuse_main(argc, argv, op, user_data));")
      argc
      argv