Fixed cwd: Removed dynamic-wind and seperated things.
This commit is contained in:
parent
6855de9ec8
commit
2c5a392584
111
scsh/scsh.scm
111
scsh/scsh.scm
|
@ -118,8 +118,16 @@
|
||||||
(define-record env
|
(define-record env
|
||||||
c-struct ; An alien -- pointer to an envvec struct
|
c-struct ; An alien -- pointer to an envvec struct
|
||||||
alist) ; Corresponding alist
|
alist) ; Corresponding alist
|
||||||
;;; TODO Give it a finaliser that uses free() to release the envvec struct.
|
|
||||||
;;; TODO Maintain alist
|
;;; Once more, Olin's define-record is not sufficient
|
||||||
|
(define (make-environ c-struct alist)
|
||||||
|
(let ((env (make-env c-struct alist)))
|
||||||
|
(add-finalizer! env env-finalizer)
|
||||||
|
env))
|
||||||
|
|
||||||
|
(define (env-finalizer env)
|
||||||
|
(display "freeing env")
|
||||||
|
(%free-env (env:c-struct env)))
|
||||||
|
|
||||||
(define env-lock (make-lock))
|
(define env-lock (make-lock))
|
||||||
(define (obtain-env-lock) (obtain-lock env-lock)) ; Thunks for
|
(define (obtain-env-lock) (obtain-lock env-lock)) ; Thunks for
|
||||||
|
@ -134,7 +142,7 @@
|
||||||
(%align-env (env:c-struct (current-env))))
|
(%align-env (env:c-struct (current-env))))
|
||||||
|
|
||||||
(define (make-threads-env alist)
|
(define (make-threads-env alist)
|
||||||
(make-env (alist->envvec alist) alist))
|
(make-environ (alist->envvec alist) alist))
|
||||||
|
|
||||||
(define (current-env) (fluid $current-env))
|
(define (current-env) (fluid $current-env))
|
||||||
|
|
||||||
|
@ -169,24 +177,33 @@
|
||||||
(define (alist->env alist)
|
(define (alist->env alist)
|
||||||
(with-env-aligned*
|
(with-env-aligned*
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(envvec-alist->env alist))))
|
(let ((env (current-env)))
|
||||||
|
(envvec-alist->env alist)
|
||||||
|
(set-env:alist env alist)))))
|
||||||
|
|
||||||
(define (delete-env name)
|
(define (delete-env name)
|
||||||
(with-env-aligned*
|
(let ((env (current-env)))
|
||||||
(lambda ()
|
(set-env:alist env (alist-delete name (env:alist env))))
|
||||||
(envvec-delete-env name))))
|
(envvec-delete-env name))
|
||||||
|
|
||||||
(define (setenv name value)
|
(define (setenv name value)
|
||||||
(with-env-aligned*
|
(with-env-aligned*
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(if name
|
(if value
|
||||||
(envvec-setenv name value)
|
(begin
|
||||||
(envvec-delete-env name)))))
|
(envvec-setenv name value)
|
||||||
|
(let ((env (current-env)))
|
||||||
|
(set-env:alist env (alist-update name value (env:alist env)))))
|
||||||
|
(delete-env name)))))
|
||||||
|
|
||||||
(define (getenv name)
|
(define (getenv name)
|
||||||
(with-env-aligned*
|
(with-env-aligned*
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(envvec-getenv name))))
|
(let* ((here (assoc name (env:alist (current-env))))
|
||||||
|
(here (if here (cdr here) here)))
|
||||||
|
(if (not (equal? here (envvec-getenv name)))
|
||||||
|
(error "not equal" here (envvec-getenv name))
|
||||||
|
here)))))
|
||||||
|
|
||||||
|
|
||||||
;;; These two functions are obsoleted by the more general INFIX-SPLITTER and
|
;;; These two functions are obsoleted by the more general INFIX-SPLITTER and
|
||||||
|
@ -269,6 +286,8 @@
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;; working directory per thread
|
;;; working directory per thread
|
||||||
|
|
||||||
|
;;; this reflects the cwd of the process
|
||||||
(define-record cache
|
(define-record cache
|
||||||
cwd)
|
cwd)
|
||||||
|
|
||||||
|
@ -276,18 +295,52 @@
|
||||||
(lambda (cache)
|
(lambda (cache)
|
||||||
(set-cache:cwd cache ""))) ; set the cache to an impossible filename.
|
(set-cache:cwd cache ""))) ; set the cache to an impossible filename.
|
||||||
|
|
||||||
(define unix-cwd
|
(define *unix-cwd*
|
||||||
(make-cache "")) ; Initialise the cache to an impossible filename.
|
(make-cache "")) ; Initialise the cache to an impossible filename.
|
||||||
|
|
||||||
(define cwd-lock (make-lock))
|
(define (unix-cwd)
|
||||||
(define (obtain-cwd-lock) (obtain-lock cwd-lock)) ; Thunks for
|
(cache:cwd *unix-cwd*))
|
||||||
(define (release-cwd-lock) (release-lock cwd-lock)) ; DYNAMIC-WINDs.
|
|
||||||
|
|
||||||
;;; The thread-specific CWD.
|
(define cwd-lock (make-lock))
|
||||||
|
|
||||||
|
;;; Actually do the syscall and update the cache
|
||||||
|
;;; assumes the cwd lock obtained
|
||||||
|
(define (chdir-and-cache dir)
|
||||||
|
(process-chdir dir)
|
||||||
|
(set-cache:cwd *unix-cwd* (process-cwd)))
|
||||||
|
|
||||||
|
;;; Dynamic-wind is not the rigth thing to take care of the lock;
|
||||||
|
;;; it would release the lock on every context switch.
|
||||||
|
;;; With-lock releases the lock on a condition, using call/cc will
|
||||||
|
;;; skrew things up
|
||||||
|
|
||||||
|
;;; Should be moved somewhere else
|
||||||
|
(define (with-lock lock thunk)
|
||||||
|
(with-handler (lambda (condition more)
|
||||||
|
(release-lock lock)
|
||||||
|
(more))
|
||||||
|
(lambda ()
|
||||||
|
(obtain-lock lock)
|
||||||
|
(let ((result (thunk)))
|
||||||
|
(release-lock lock)
|
||||||
|
result))))
|
||||||
|
|
||||||
|
;;; The thread-specific CWD: A fluid
|
||||||
(define $cwd (make-fluid (process-cwd)))
|
(define $cwd (make-fluid (process-cwd)))
|
||||||
|
|
||||||
(define (cwd) (fluid $cwd))
|
(define (cwd) (fluid $cwd))
|
||||||
(define (with-cwd* dir thunk) (let-fluid $cwd dir thunk))
|
|
||||||
(define (set-cwd! dir) (set-fluid! $cwd dir))
|
(define (set-cwd! dir) (set-fluid! $cwd dir))
|
||||||
|
(define (let-cwd dir thunk)
|
||||||
|
(let-fluid $cwd dir thunk))
|
||||||
|
|
||||||
|
(define (with-cwd* dir thunk)
|
||||||
|
(let ((changed-dir #f))
|
||||||
|
(with-lock cwd-lock
|
||||||
|
(lambda ()
|
||||||
|
(align-cwd!)
|
||||||
|
(chdir-and-cache dir)
|
||||||
|
(set! changed-dir (unix-cwd))))
|
||||||
|
(let-cwd changed-dir thunk)))
|
||||||
|
|
||||||
;; Align the Unix CWD with the scsh CWD.
|
;; Align the Unix CWD with the scsh CWD.
|
||||||
;; Since another thread could disalign, this call and
|
;; Since another thread could disalign, this call and
|
||||||
|
@ -296,16 +349,16 @@
|
||||||
|
|
||||||
(define (align-cwd!)
|
(define (align-cwd!)
|
||||||
(let ((dir (cwd)))
|
(let ((dir (cwd)))
|
||||||
(if (not (string=? (cwd) (cache:cwd unix-cwd)))
|
(if (not (string=? dir (unix-cwd)))
|
||||||
(begin (process-chdir dir)
|
(chdir-and-cache dir))))
|
||||||
(set-cache:cwd unix-cwd dir)))))
|
|
||||||
|
|
||||||
(define (chdir dir)
|
(define (chdir dir)
|
||||||
(dynamic-wind obtain-cwd-lock
|
(with-lock cwd-lock
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(process-chdir dir)
|
(align-cwd!)
|
||||||
(set-cwd! (process-cwd)))
|
(chdir-and-cache dir)
|
||||||
release-cwd-lock))
|
(set-cwd! (unix-cwd)))))
|
||||||
|
|
||||||
;;; For thunks that don't raise exceptions or throw to continuations,
|
;;; For thunks that don't raise exceptions or throw to continuations,
|
||||||
;;; this is overkill & probably a little heavyweight for frequent use.
|
;;; this is overkill & probably a little heavyweight for frequent use.
|
||||||
|
@ -319,9 +372,11 @@
|
||||||
;;; the syscall, turn them back on.
|
;;; the syscall, turn them back on.
|
||||||
|
|
||||||
(define (with-cwd-aligned* thunk)
|
(define (with-cwd-aligned* thunk)
|
||||||
(dynamic-wind obtain-cwd-lock
|
(dynamic-wind (lambda ()
|
||||||
(lambda () (dynamic-wind align-cwd! thunk values))
|
(with-lock cwd-lock
|
||||||
release-cwd-lock))
|
align-cwd!))
|
||||||
|
thunk
|
||||||
|
values))
|
||||||
|
|
||||||
;;; example syscall
|
;;; example syscall
|
||||||
;;; (define (exported-delete-file fname)
|
;;; (define (exported-delete-file fname)
|
||||||
|
|
Loading…
Reference in New Issue