add `filesystem-change-evt'
The `filesystem-change-evt' function takes a path to a file or directory and returns an event that becomes ready when the file or directory changes (conservatively, so false positives are possible). These events are supported on Linux, Mac OS X and other BSD variants with kqueue(), and Windows.
This commit is contained in:
parent
5d58b2d14d
commit
3b0566ea0a
|
@ -473,6 +473,73 @@ On Windows, an element of the result list may start with
|
||||||
Returns a list of all current root directories. Obtaining this list
|
Returns a list of all current root directories. Obtaining this list
|
||||||
can be particularly slow on Windows.}
|
can be particularly slow on Windows.}
|
||||||
|
|
||||||
|
@;------------------------------------------------------------------------
|
||||||
|
@section[#:tag "filesystem-change"]{Detecting Filesystem Changes}
|
||||||
|
|
||||||
|
Many operating systems provide notifications for filesystem changes,
|
||||||
|
and those notifications are reflected in Racket by @tech{filesystem
|
||||||
|
change events}.
|
||||||
|
|
||||||
|
@defproc[(filesystem-change-evt? [v any/c]) boolean?]{
|
||||||
|
|
||||||
|
Returns @racket[#f] if @racket[v] is a @tech{filesystem change
|
||||||
|
event}, @racket[#f] otherwise.}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc*[([(filesystem-change-evt [path path-string?])
|
||||||
|
filesystem-change-evt?]
|
||||||
|
[(filesystem-change-evt [path path-string?]
|
||||||
|
[failure-thunk (-> any)])
|
||||||
|
any])]{
|
||||||
|
|
||||||
|
Creates a @deftech{filesystem change event}, which is
|
||||||
|
@tech{synchronizable event} that becomes @tech{ready for
|
||||||
|
synchronization} after a change to @racket[path]:
|
||||||
|
|
||||||
|
@itemlist[
|
||||||
|
|
||||||
|
@item{If @racket[path] refers to a file, the event becomes
|
||||||
|
@tech{ready for synchronization} when the file's content or
|
||||||
|
attributes change, or when the file is deleted.}
|
||||||
|
|
||||||
|
@item{If @racket[path] refers to a directory, the event becomes
|
||||||
|
@tech{ready for synchronization} if a file or subdirectory is
|
||||||
|
added, renamed, or removed within the directory.}
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
The event also becomes @tech{ready for synchronization} if
|
||||||
|
it is passed to @racket[filesystem-change-evt-cancel].
|
||||||
|
|
||||||
|
Finally, depending on the precision of information available from the
|
||||||
|
operating system, the event may become @tech{ready for
|
||||||
|
synchronization} under other circumstances. For example, on
|
||||||
|
Windows, an event for a file becomes ready when any file changes
|
||||||
|
within in the same directory as the file.
|
||||||
|
|
||||||
|
If the current platform does not support filesystem-change
|
||||||
|
notifications, then the @exnraise[exn:fail:unsupported] if
|
||||||
|
@racket[failure-thunk] is not provided, or @racket[failure-thunk] is
|
||||||
|
called in tail position if provided. Similarly, if there is any
|
||||||
|
operating-system error when creating the event (such as a non-existent
|
||||||
|
file), then the @exnraise[exn:fail:filesystem] or @racket[failure-thunk]
|
||||||
|
is called.
|
||||||
|
|
||||||
|
A @tech{filesystem change event} is placed under the management of the
|
||||||
|
@tech{current custodian} when it is created. If the @tech{custodian}
|
||||||
|
is shut down, @racket[filesystem-change-evt-cancel] is applied to the
|
||||||
|
event.}
|
||||||
|
|
||||||
|
|
||||||
|
@defproc[(filesystem-change-evt-cancel [evt filesystem-change-evt?])
|
||||||
|
void?]{
|
||||||
|
|
||||||
|
Causes @racket[evt] to become immediately @tech{ready for
|
||||||
|
synchronization}, whether it was ready or before not, and releases and
|
||||||
|
resources (at the operating system level) for tracking filesystem
|
||||||
|
changes.}
|
||||||
|
|
||||||
|
|
||||||
@;------------------------------------------------------------------------
|
@;------------------------------------------------------------------------
|
||||||
@section[#:tag "runtime-path"]{Declaring Paths Needed at Run Time}
|
@section[#:tag "runtime-path"]{Declaring Paths Needed at Run Time}
|
||||||
|
|
||||||
|
|
|
@ -1378,6 +1378,93 @@
|
||||||
'(close-input-port r2))))
|
'(close-input-port r2))))
|
||||||
(tcp-close l))
|
(tcp-close l))
|
||||||
|
|
||||||
|
;;----------------------------------------------------------------------
|
||||||
|
;; Filesystem-change events
|
||||||
|
|
||||||
|
(test #f filesystem-change-evt? 'evt)
|
||||||
|
|
||||||
|
(let ([dir (make-temporary-file "change~a" 'directory)])
|
||||||
|
(define known-file-supported?
|
||||||
|
(case (system-type)
|
||||||
|
[(macosx) #t]
|
||||||
|
[else #f]))
|
||||||
|
(define known-supported?
|
||||||
|
(or known-file-supported?
|
||||||
|
(case (system-type)
|
||||||
|
[(windows) #t]
|
||||||
|
[else #f])))
|
||||||
|
(define (check-supported evt file?)
|
||||||
|
(when (if file?
|
||||||
|
known-file-supported?
|
||||||
|
known-supported?)
|
||||||
|
(test #t filesystem-change-evt? evt)))
|
||||||
|
|
||||||
|
(define (check f1-name f2-name as-file? known-x-supported?)
|
||||||
|
(printf "checking ~s, ~s as ~a\n" f1-name f2-name (if as-file? "file" "dir"))
|
||||||
|
(define f1 (build-path dir f1-name))
|
||||||
|
(define f2 (build-path dir f2-name))
|
||||||
|
|
||||||
|
(define dir-e (filesystem-change-evt dir (lambda () #f)))
|
||||||
|
(check-supported dir-e #f)
|
||||||
|
(if as-file?
|
||||||
|
(call-with-output-file* f1 (lambda (o) (fprintf o "1\n")))
|
||||||
|
(make-directory f1))
|
||||||
|
(when dir-e
|
||||||
|
(test dir-e sync dir-e)
|
||||||
|
(test dir-e sync dir-e))
|
||||||
|
(if as-file?
|
||||||
|
(call-with-output-file* f2 (lambda (o) (fprintf o "2\n")))
|
||||||
|
(make-directory f2))
|
||||||
|
|
||||||
|
(define f1-e (filesystem-change-evt f1 (lambda () #f)))
|
||||||
|
(define f2-e (filesystem-change-evt f2 (lambda () #f)))
|
||||||
|
(check-supported f1-e #t)
|
||||||
|
(check-supported f2-e #t)
|
||||||
|
|
||||||
|
(when f1-e
|
||||||
|
(test #f sync/timeout 0 f1-e)
|
||||||
|
(test #f sync/timeout 0 f2-e)
|
||||||
|
|
||||||
|
(call-with-output-file (if as-file?
|
||||||
|
f1
|
||||||
|
(build-path f1 "x"))
|
||||||
|
#:exists 'append
|
||||||
|
(lambda (o) (newline o)))
|
||||||
|
(test f1-e sync f1-e)
|
||||||
|
(when known-x-supported?
|
||||||
|
(test #f sync/timeout 0 f2-e))
|
||||||
|
|
||||||
|
(call-with-output-file (if as-file?
|
||||||
|
f2
|
||||||
|
(build-path f2 "y"))
|
||||||
|
#:exists 'append
|
||||||
|
(lambda (o) (newline o)))
|
||||||
|
(test f2-e sync/timeout 0 f2-e)
|
||||||
|
(test f2-e sync f2-e)
|
||||||
|
(test f1-e sync f1-e)
|
||||||
|
|
||||||
|
(define f1-e2 (filesystem-change-evt f1 (lambda () #f)))
|
||||||
|
(when known-x-supported?
|
||||||
|
(test #f sync/timeout 0 f1-e2))
|
||||||
|
(test f1-e sync/timeout 0 f1-e)
|
||||||
|
(test f1-e sync f1-e)
|
||||||
|
|
||||||
|
(filesystem-change-evt-cancel f1-e2)
|
||||||
|
(test f1-e2 sync/timeout 0 f1-e2)
|
||||||
|
|
||||||
|
(define cust (make-custodian))
|
||||||
|
(define f1-e3 (parameterize ([current-custodian cust])
|
||||||
|
(filesystem-change-evt f2 (lambda () #f))))
|
||||||
|
(when known-x-supported?
|
||||||
|
(test #f sync/timeout 0 f1-e3))
|
||||||
|
(custodian-shutdown-all cust)
|
||||||
|
(test f1-e3 sync/timeout 0 f1-e3)))
|
||||||
|
|
||||||
|
(check "f1" "f2" #t known-file-supported?)
|
||||||
|
(check "f1d" "f2d" #f known-supported?)
|
||||||
|
|
||||||
|
(delete-directory/files dir))
|
||||||
|
|
||||||
;;----------------------------------------------------------------------
|
;;----------------------------------------------------------------------
|
||||||
;; TCP
|
;; TCP
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
Version 5.3.900.4
|
||||||
|
Added filesystem-change-evt, filesystem-change-evt?, and
|
||||||
|
filesystem-change-evt-cancel
|
||||||
|
|
||||||
Version 5.3.900.2
|
Version 5.3.900.2
|
||||||
Changed link-file handling to separate "user" and "shared" modes;
|
Changed link-file handling to separate "user" and "shared" modes;
|
||||||
removed 'links-file mode for find-system-path, PLTLINKSFILE
|
removed 'links-file mode for find-system-path, PLTLINKSFILE
|
||||||
|
|
56
racket/src/configure
vendored
56
racket/src/configure
vendored
|
@ -4080,6 +4080,7 @@ case "$host_os" in
|
||||||
DYN_CFLAGS="-fPIC"
|
DYN_CFLAGS="-fPIC"
|
||||||
try_poll_syscall=yes
|
try_poll_syscall=yes
|
||||||
try_epoll_syscall=yes
|
try_epoll_syscall=yes
|
||||||
|
try_inotify_syscall=yes
|
||||||
case "$host_cpu" in
|
case "$host_cpu" in
|
||||||
#Required for CentOS 4.6
|
#Required for CentOS 4.6
|
||||||
x86_64)
|
x86_64)
|
||||||
|
@ -5473,6 +5474,61 @@ _ACEOF
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "${try_inotify_syscall}" = "yes" ; then
|
||||||
|
msg="for inotify"
|
||||||
|
{ echo "$as_me:$LINENO: checking $msg" >&5
|
||||||
|
echo $ECHO_N "checking $msg... $ECHO_C" >&6; }
|
||||||
|
cat >conftest.$ac_ext <<_ACEOF
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
int main() {
|
||||||
|
int fd;
|
||||||
|
int wd;
|
||||||
|
fd = inotify_init();
|
||||||
|
wd = inotify_add_watch(fd, "/tmp",
|
||||||
|
(IN_CREATE | IN_DELETE | IN_DELETE_SELF
|
||||||
|
| IN_MODIFY | IN_MOVE_SELF | IN_MOVED_TO));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||||
|
if { (ac_try="$ac_link"
|
||||||
|
case "(($ac_try" in
|
||||||
|
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||||
|
*) ac_try_echo=$ac_try;;
|
||||||
|
esac
|
||||||
|
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||||
|
(eval "$ac_link") 2>conftest.er1
|
||||||
|
ac_status=$?
|
||||||
|
grep -v '^ *+' conftest.er1 >conftest.err
|
||||||
|
rm -f conftest.er1
|
||||||
|
cat conftest.err >&5
|
||||||
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); } && {
|
||||||
|
test -z "$ac_c_werror_flag" ||
|
||||||
|
test ! -s conftest.err
|
||||||
|
} && test -s conftest$ac_exeext &&
|
||||||
|
$as_test_x conftest$ac_exeext; then
|
||||||
|
use_inotify=yes
|
||||||
|
else
|
||||||
|
echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
|
use_inotify=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
{ echo "$as_me:$LINENO: result: $use_inotify" >&5
|
||||||
|
echo "${ECHO_T}$use_inotify" >&6; }
|
||||||
|
if test "${use_inotify}" = "yes" ; then
|
||||||
|
|
||||||
|
cat >>confdefs.h <<\_ACEOF
|
||||||
|
#define HAVE_INOTIFY_SYSCALL 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if test "${try_kqueue_syscall}" = "yes" ; then
|
if test "${try_kqueue_syscall}" = "yes" ; then
|
||||||
msg="for kqueue"
|
msg="for kqueue"
|
||||||
{ echo "$as_me:$LINENO: checking $msg" >&5
|
{ echo "$as_me:$LINENO: checking $msg" >&5
|
||||||
|
|
|
@ -579,6 +579,7 @@ case "$host_os" in
|
||||||
DYN_CFLAGS="-fPIC"
|
DYN_CFLAGS="-fPIC"
|
||||||
try_poll_syscall=yes
|
try_poll_syscall=yes
|
||||||
try_epoll_syscall=yes
|
try_epoll_syscall=yes
|
||||||
|
try_inotify_syscall=yes
|
||||||
case "$host_cpu" in
|
case "$host_cpu" in
|
||||||
#Required for CentOS 4.6
|
#Required for CentOS 4.6
|
||||||
x86_64)
|
x86_64)
|
||||||
|
@ -964,6 +965,26 @@ if test "${try_epoll_syscall}" = "yes" ; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "${try_inotify_syscall}" = "yes" ; then
|
||||||
|
[ msg="for inotify" ]
|
||||||
|
AC_MSG_CHECKING($msg)
|
||||||
|
AC_LINK_IFELSE(
|
||||||
|
[ #include <sys/inotify.h> ]
|
||||||
|
int main() {
|
||||||
|
int fd;
|
||||||
|
int wd;
|
||||||
|
fd = inotify_init();
|
||||||
|
wd = inotify_add_watch(fd, "/tmp",
|
||||||
|
(IN_CREATE | IN_DELETE | IN_DELETE_SELF
|
||||||
|
| IN_MODIFY | IN_MOVE_SELF | IN_MOVED_TO));
|
||||||
|
return 0;
|
||||||
|
}, use_inotify=yes, use_inotify=no)
|
||||||
|
AC_MSG_RESULT($use_inotify)
|
||||||
|
if test "${use_inotify}" = "yes" ; then
|
||||||
|
AC_DEFINE(HAVE_INOTIFY_SYSCALL,1,[Have inotify])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if test "${try_kqueue_syscall}" = "yes" ; then
|
if test "${try_kqueue_syscall}" = "yes" ; then
|
||||||
[ msg="for kqueue" ]
|
[ msg="for kqueue" ]
|
||||||
AC_MSG_CHECKING($msg)
|
AC_MSG_CHECKING($msg)
|
||||||
|
|
|
@ -2105,6 +2105,8 @@ extern Scheme_Extension_Table *scheme_extension_table;
|
||||||
#define MZFD_CHECK_READ 3
|
#define MZFD_CHECK_READ 3
|
||||||
#define MZFD_CHECK_WRITE 4
|
#define MZFD_CHECK_WRITE 4
|
||||||
#define MZFD_REMOVE 5
|
#define MZFD_REMOVE 5
|
||||||
|
#define MZFD_CREATE_VNODE 6
|
||||||
|
#define MZFD_CHECK_VNODE 7
|
||||||
|
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
|
|
||||||
|
|
|
@ -56,9 +56,10 @@ typedef unsigned long uintptr_t;
|
||||||
/* Whether pthread_rwlock is available. */
|
/* Whether pthread_rwlock is available. */
|
||||||
#undef HAVE_PTHREAD_RWLOCK
|
#undef HAVE_PTHREAD_RWLOCK
|
||||||
|
|
||||||
/* When poll(), epoll(), and/or kqueue() is available: */
|
/* When poll(), epoll(), kqueue(), etc. is available: */
|
||||||
#undef HAVE_POLL_SYSCALL
|
#undef HAVE_POLL_SYSCALL
|
||||||
#undef HAVE_EPOLL_SYSCALL
|
#undef HAVE_EPOLL_SYSCALL
|
||||||
|
#undef HAVE_INOTIFY_SYSCALL
|
||||||
#undef HAVE_KQUEUE_SYSCALL
|
#undef HAVE_KQUEUE_SYSCALL
|
||||||
|
|
||||||
/* When mmap() and mprotect() are available: */
|
/* When mmap() and mprotect() are available: */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -201,3 +201,28 @@ static int mark_read_write_evt_FIXUP(void *p, struct NewGC *gc) {
|
||||||
#define mark_read_write_evt_IS_CONST_SIZE 1
|
#define mark_read_write_evt_IS_CONST_SIZE 1
|
||||||
|
|
||||||
|
|
||||||
|
static int mark_filesystem_change_evt_SIZE(void *p, struct NewGC *gc) {
|
||||||
|
return
|
||||||
|
gcBYTES_TO_WORDS(sizeof(Scheme_Filesystem_Change_Evt));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mark_filesystem_change_evt_MARK(void *p, struct NewGC *gc) {
|
||||||
|
Scheme_Filesystem_Change_Evt *fc = (Scheme_Filesystem_Change_Evt *)p;
|
||||||
|
gcMARK2(fc->sema, gc);
|
||||||
|
gcMARK2(fc->mref, gc);
|
||||||
|
return
|
||||||
|
gcBYTES_TO_WORDS(sizeof(Scheme_Filesystem_Change_Evt));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mark_filesystem_change_evt_FIXUP(void *p, struct NewGC *gc) {
|
||||||
|
Scheme_Filesystem_Change_Evt *fc = (Scheme_Filesystem_Change_Evt *)p;
|
||||||
|
gcFIXUP2(fc->sema, gc);
|
||||||
|
gcFIXUP2(fc->mref, gc);
|
||||||
|
return
|
||||||
|
gcBYTES_TO_WORDS(sizeof(Scheme_Filesystem_Change_Evt));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define mark_filesystem_change_evt_IS_ATOMIC 0
|
||||||
|
#define mark_filesystem_change_evt_IS_CONST_SIZE 1
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1738,6 +1738,15 @@ mark_read_write_evt {
|
||||||
gcBYTES_TO_WORDS(sizeof(Scheme_Read_Write_Evt));
|
gcBYTES_TO_WORDS(sizeof(Scheme_Read_Write_Evt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mark_filesystem_change_evt {
|
||||||
|
mark:
|
||||||
|
Scheme_Filesystem_Change_Evt *fc = (Scheme_Filesystem_Change_Evt *)p;
|
||||||
|
gcMARK2(fc->sema, gc);
|
||||||
|
gcMARK2(fc->mref, gc);
|
||||||
|
size:
|
||||||
|
gcBYTES_TO_WORDS(sizeof(Scheme_Filesystem_Change_Evt));
|
||||||
|
}
|
||||||
|
|
||||||
END port;
|
END port;
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
|
@ -51,6 +51,9 @@
|
||||||
# ifdef HAVE_POLL_SYSCALL
|
# ifdef HAVE_POLL_SYSCALL
|
||||||
# include <poll.h>
|
# include <poll.h>
|
||||||
# endif
|
# endif
|
||||||
|
# ifdef HAVE_INOTIFY_SYSCALL
|
||||||
|
# include <sys/inotify.h>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ITIMER
|
#ifdef USE_ITIMER
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
|
@ -443,6 +446,14 @@ static void rw_evt_wakeup(Scheme_Object *rww, void *fds);
|
||||||
|
|
||||||
static int progress_evt_ready(Scheme_Object *rww, Scheme_Schedule_Info *sinfo);
|
static int progress_evt_ready(Scheme_Object *rww, Scheme_Schedule_Info *sinfo);
|
||||||
static int closed_evt_ready(Scheme_Object *rww, Scheme_Schedule_Info *sinfo);
|
static int closed_evt_ready(Scheme_Object *rww, Scheme_Schedule_Info *sinfo);
|
||||||
|
static int filesystem_change_evt_ready(Scheme_Object *evt, Scheme_Schedule_Info *sinfo);
|
||||||
|
|
||||||
|
#ifdef DOS_FILE_SYSTEM
|
||||||
|
static void filesystem_change_evt_need_wakeup (Scheme_Object *port, void *fds);
|
||||||
|
#else
|
||||||
|
# define filesystem_change_evt_need_wakeup NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static Scheme_Object *
|
static Scheme_Object *
|
||||||
_scheme_make_named_file_input_port(FILE *fp, Scheme_Object *name, int regfile);
|
_scheme_make_named_file_input_port(FILE *fp, Scheme_Object *name, int regfile);
|
||||||
|
@ -483,6 +494,13 @@ THREAD_LOCAL_DECL(static char *read_string_byte_buffer);
|
||||||
|
|
||||||
#include "schwinfd.h"
|
#include "schwinfd.h"
|
||||||
|
|
||||||
|
typedef struct Scheme_Filesystem_Change_Evt {
|
||||||
|
Scheme_Object so;
|
||||||
|
intptr_t fd;
|
||||||
|
Scheme_Object *sema;
|
||||||
|
Scheme_Custodian_Reference *mref;
|
||||||
|
} Scheme_Filesystem_Change_Evt;
|
||||||
|
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
/* initialization */
|
/* initialization */
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
|
@ -627,6 +645,8 @@ void scheme_init_port_wait()
|
||||||
scheme_add_evt(scheme_progress_evt_type, (Scheme_Ready_Fun)progress_evt_ready, NULL, NULL, 1);
|
scheme_add_evt(scheme_progress_evt_type, (Scheme_Ready_Fun)progress_evt_ready, NULL, NULL, 1);
|
||||||
scheme_add_evt(scheme_write_evt_type, (Scheme_Ready_Fun)rw_evt_ready, rw_evt_wakeup, NULL, 1);
|
scheme_add_evt(scheme_write_evt_type, (Scheme_Ready_Fun)rw_evt_ready, rw_evt_wakeup, NULL, 1);
|
||||||
scheme_add_evt(scheme_port_closed_evt_type, (Scheme_Ready_Fun)closed_evt_ready, NULL, NULL, 1);
|
scheme_add_evt(scheme_port_closed_evt_type, (Scheme_Ready_Fun)closed_evt_ready, NULL, NULL, 1);
|
||||||
|
scheme_add_evt(scheme_filesystem_change_evt_type, (Scheme_Ready_Fun)filesystem_change_evt_ready,
|
||||||
|
filesystem_change_evt_need_wakeup, NULL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheme_init_port_places(void)
|
void scheme_init_port_places(void)
|
||||||
|
@ -5952,6 +5972,243 @@ Scheme_Object *scheme_file_unlock(int argc, Scheme_Object **argv)
|
||||||
return scheme_void;
|
return scheme_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*========================================================================*/
|
||||||
|
/* filesystem change events */
|
||||||
|
/*========================================================================*/
|
||||||
|
|
||||||
|
Scheme_Object *scheme_filesystem_change_evt(Scheme_Object *path, int flags, int signal_errs)
|
||||||
|
{
|
||||||
|
char *filename;
|
||||||
|
int ok = 0, errid = 0;
|
||||||
|
intptr_t fd;
|
||||||
|
|
||||||
|
filename = scheme_expand_string_filename(path,
|
||||||
|
"filesystem-change-evt",
|
||||||
|
NULL,
|
||||||
|
SCHEME_GUARD_FILE_EXISTS);
|
||||||
|
#if defined(HAVE_KQUEUE_SYSCALL)
|
||||||
|
do {
|
||||||
|
fd = open(filename, flags | MZ_BINARY, 0666);
|
||||||
|
} while ((fd == -1) && (errno == EINTR));
|
||||||
|
if (fd == -1)
|
||||||
|
errid = errno;
|
||||||
|
else
|
||||||
|
ok = 1;
|
||||||
|
#elif defined(HAVE_INOTIFY_SYSCALL)
|
||||||
|
/* This implementation uses a file descriptor for every event,
|
||||||
|
instead of using a watch descriptor for every event. This could
|
||||||
|
be improved, but note that the kqueue() implementation needs a
|
||||||
|
file descriptor per event, anyway. */
|
||||||
|
fd = inotify_init();
|
||||||
|
if (fd == -1)
|
||||||
|
errid = errno;
|
||||||
|
else {
|
||||||
|
int wd;
|
||||||
|
wd = inotify_add_watch(fd, filename,
|
||||||
|
(IN_CREATE | IN_DELETE | IN_DELETE_SELF
|
||||||
|
| IN_MODIFY | IN_MOVE_SELF | IN_MOVED_TO
|
||||||
|
| IN_ATTRIB | IN_ONESHOT));
|
||||||
|
if (wd == -1) {
|
||||||
|
errid = errno;
|
||||||
|
scheme_close_file_fd(fd);
|
||||||
|
} else {
|
||||||
|
ok = 1;
|
||||||
|
fcntl(fd, F_SETFL, MZ_NONBLOCKING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif defined(DOS_FILE_SYSTEM)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
char *try_filename = filename;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
h = FindFirstChangeNotification(try_filename, FALSE,
|
||||||
|
(FILE_NOTIFY_CHANGE_FILE_NAME
|
||||||
|
| FILE_NOTIFY_CHANGE_DIR_NAME
|
||||||
|
| FILE_NOTIFY_CHANGE_SIZE
|
||||||
|
| FILE_NOTIFY_CHANGE_LAST_WRITE
|
||||||
|
| FILE_NOTIFY_CHANGE_ATTRIBUTES));
|
||||||
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
|
/* If `filename' refers to a file, then monitor its enclosing directory. */
|
||||||
|
errid = GetLastError();
|
||||||
|
if ((try_filename == filename) && scheme_file_exists(filename)) {
|
||||||
|
Scheme_Object *base, *name;
|
||||||
|
int is_dir;
|
||||||
|
name = scheme_split_path(filename, strlen(filename), &base, &is_dir, SCHEME_PLATFORM_PATH_KIND);
|
||||||
|
try_filename = scheme_expand_string_filename(base,
|
||||||
|
"filesystem-change-evt",
|
||||||
|
NULL,
|
||||||
|
SCHEME_GUARD_FILE_EXISTS);
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
fd = (intptr_t)h;
|
||||||
|
ok = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define NO_FILESYSTEM_CHANGE_EVTS
|
||||||
|
ok = 0;
|
||||||
|
errid = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
if (signal_errs) {
|
||||||
|
#ifdef NO_FILESYSTEM_CHANGE_EVTS
|
||||||
|
scheme_raise_exn(MZEXN_FAIL_UNSUPPORTED,
|
||||||
|
"filesystem-change-evt: " NOT_SUPPORTED_STR "\n"
|
||||||
|
" path: %q\n",
|
||||||
|
filename);
|
||||||
|
#else
|
||||||
|
scheme_raise_exn(MZEXN_FAIL_FILESYSTEM,
|
||||||
|
"filesystem-change-evt: error generating event\n"
|
||||||
|
" path: %q\n"
|
||||||
|
" system error: %E",
|
||||||
|
filename,
|
||||||
|
errid);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(NO_FILESYSTEM_CHANGE_EVTS)
|
||||||
|
return NULL;
|
||||||
|
#elif defined(DOS_FILE_SYSTEM)
|
||||||
|
{
|
||||||
|
Scheme_Filesystem_Change_Evt *fc;
|
||||||
|
Scheme_Custodian_Reference *mref;
|
||||||
|
|
||||||
|
fc = MALLOC_ONE_TAGGED(Scheme_Filesystem_Change_Evt);
|
||||||
|
fc->so.type = scheme_filesystem_change_evt_type;
|
||||||
|
fc->fd = fd;
|
||||||
|
|
||||||
|
mref = scheme_add_managed(NULL, (Scheme_Object *)fc, scheme_filesystem_change_evt_cancel, NULL, 1);
|
||||||
|
fc->mref = mref;
|
||||||
|
|
||||||
|
return (Scheme_Object *)fc;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
Scheme_Filesystem_Change_Evt *fc;
|
||||||
|
Scheme_Object *sema;
|
||||||
|
Scheme_Custodian_Reference *mref;
|
||||||
|
|
||||||
|
sema = scheme_fd_to_semaphore(fd, MZFD_CREATE_VNODE, 0);
|
||||||
|
if (!sema) {
|
||||||
|
const char *reason = "";
|
||||||
|
|
||||||
|
#if defined(HAVE_KQUEUE_SYSCALL)
|
||||||
|
if (!scheme_fd_regular_file(fd, 1))
|
||||||
|
reason = ";\n not a regular file or directory";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
scheme_close_file_fd(fd);
|
||||||
|
|
||||||
|
if (signal_errs) {
|
||||||
|
scheme_raise_exn(MZEXN_FAIL_FILESYSTEM,
|
||||||
|
"filesystem-change-evt: cannot generate event%s\n"
|
||||||
|
" path: %q",
|
||||||
|
reason,
|
||||||
|
filename);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fc = MALLOC_ONE_TAGGED(Scheme_Filesystem_Change_Evt);
|
||||||
|
fc->so.type = scheme_filesystem_change_evt_type;
|
||||||
|
fc->fd = fd;
|
||||||
|
fc->sema = sema;
|
||||||
|
|
||||||
|
mref = scheme_add_managed(NULL, (Scheme_Object *)fc, scheme_filesystem_change_evt_cancel, NULL, 1);
|
||||||
|
fc->mref = mref;
|
||||||
|
|
||||||
|
return (Scheme_Object *)fc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void scheme_filesystem_change_evt_cancel(Scheme_Object *evt, void *ignored_data)
|
||||||
|
{
|
||||||
|
#ifndef NO_FILESYSTEM_CHANGE_EVTS
|
||||||
|
Scheme_Filesystem_Change_Evt *fc = (Scheme_Filesystem_Change_Evt *)evt;
|
||||||
|
|
||||||
|
if (fc->mref) {
|
||||||
|
# if defined(DOS_FILE_SYSTEM)
|
||||||
|
if (fc->fd) {
|
||||||
|
FindCloseChangeNotification((HANDLE)fc->fd);
|
||||||
|
fc->fd = 0;
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
(void)scheme_fd_to_semaphore(fc->fd, MZFD_REMOVE, 0);
|
||||||
|
scheme_close_file_fd(fc->fd);
|
||||||
|
scheme_post_sema_all(fc->sema);
|
||||||
|
# endif
|
||||||
|
scheme_remove_managed(fc->mref, (Scheme_Object *)fc);
|
||||||
|
fc->mref = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int filesystem_change_evt_ready(Scheme_Object *evt, Scheme_Schedule_Info *sinfo)
|
||||||
|
{
|
||||||
|
#ifndef NO_FILESYSTEM_CHANGE_EVTS
|
||||||
|
Scheme_Filesystem_Change_Evt *fc = (Scheme_Filesystem_Change_Evt *)evt;
|
||||||
|
|
||||||
|
# if defined(DOS_FILE_SYSTEM)
|
||||||
|
if (fc->fd) {
|
||||||
|
if (WaitForSingleObject((HANDLE)fc->fd, 0) == WAIT_OBJECT_0) {
|
||||||
|
FindCloseChangeNotification((HANDLE)fc->fd);
|
||||||
|
fc->fd = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !fc->fd;
|
||||||
|
# else
|
||||||
|
if (scheme_try_plain_sema(fc->sema))
|
||||||
|
scheme_filesystem_change_evt_cancel((Scheme_Object *)fc, NULL);
|
||||||
|
else
|
||||||
|
scheme_check_fd_semaphores();
|
||||||
|
scheme_set_sync_target(sinfo, fc->sema, evt, NULL, 0, 1, NULL);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DOS_FILE_SYSTEM
|
||||||
|
static void filesystem_change_evt_need_wakeup (Scheme_Object *evt, void *fds)
|
||||||
|
{
|
||||||
|
Scheme_Filesystem_Change_Evt *fc = (Scheme_Filesystem_Change_Evt *)evt;
|
||||||
|
|
||||||
|
if (fc->fd)
|
||||||
|
scheme_add_fd_handle((void *)fc->fd, fds, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int scheme_fd_regular_file(intptr_t fd, int dir_ok)
|
||||||
|
{
|
||||||
|
#if defined(USE_FD_PORTS) && !defined(DOS_FILE_SYSTEM)
|
||||||
|
int ok;
|
||||||
|
struct stat buf;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ok = fstat(fd, &buf);
|
||||||
|
} while ((ok == -1) && (errno == EINTR));
|
||||||
|
|
||||||
|
if (!S_ISREG(buf.st_mode)
|
||||||
|
&& (!dir_ok || !S_ISDIR(buf.st_mode)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
/* FILE input ports */
|
/* FILE input ports */
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
|
@ -10861,6 +11118,8 @@ static void register_traversers(void)
|
||||||
|
|
||||||
GC_REG_TRAV(scheme_subprocess_type, mark_subprocess);
|
GC_REG_TRAV(scheme_subprocess_type, mark_subprocess);
|
||||||
GC_REG_TRAV(scheme_write_evt_type, mark_read_write_evt);
|
GC_REG_TRAV(scheme_write_evt_type, mark_read_write_evt);
|
||||||
|
|
||||||
|
GC_REG_TRAV(scheme_filesystem_change_evt_type, mark_filesystem_change_evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
END_XFORM_SKIP;
|
END_XFORM_SKIP;
|
||||||
|
|
|
@ -126,6 +126,10 @@ static Scheme_Object *port_counts_lines_p(int, Scheme_Object **args);
|
||||||
static Scheme_Object *port_next_location(int, Scheme_Object **args);
|
static Scheme_Object *port_next_location(int, Scheme_Object **args);
|
||||||
static Scheme_Object *set_port_next_location(int, Scheme_Object **args);
|
static Scheme_Object *set_port_next_location(int, Scheme_Object **args);
|
||||||
|
|
||||||
|
static Scheme_Object *filesystem_change_evt(int, Scheme_Object **args);
|
||||||
|
static Scheme_Object *filesystem_change_evt_p(int, Scheme_Object **args);
|
||||||
|
static Scheme_Object *filesystem_change_evt_cancel(int, Scheme_Object **args);
|
||||||
|
|
||||||
static Scheme_Object *sch_default_read_handler(void *ignore, int argc, Scheme_Object *argv[]);
|
static Scheme_Object *sch_default_read_handler(void *ignore, int argc, Scheme_Object *argv[]);
|
||||||
static Scheme_Object *sch_default_display_handler(int argc, Scheme_Object *argv[]);
|
static Scheme_Object *sch_default_display_handler(int argc, Scheme_Object *argv[]);
|
||||||
static Scheme_Object *sch_default_write_handler(int argc, Scheme_Object *argv[]);
|
static Scheme_Object *sch_default_write_handler(int argc, Scheme_Object *argv[]);
|
||||||
|
@ -260,6 +264,10 @@ scheme_init_port_fun(Scheme_Env *env)
|
||||||
GLOBAL_PRIM_W_ARITY2("port-next-location", port_next_location, 1, 1, 3, 3, env);
|
GLOBAL_PRIM_W_ARITY2("port-next-location", port_next_location, 1, 1, 3, 3, env);
|
||||||
GLOBAL_PRIM_W_ARITY("set-port-next-location!", set_port_next_location, 4, 4, env);
|
GLOBAL_PRIM_W_ARITY("set-port-next-location!", set_port_next_location, 4, 4, env);
|
||||||
|
|
||||||
|
GLOBAL_PRIM_W_ARITY("filesystem-change-evt", filesystem_change_evt, 1, 2, env);
|
||||||
|
GLOBAL_NONCM_PRIM("filesystem-change-evt?", filesystem_change_evt_p, 1, 1, env);
|
||||||
|
GLOBAL_NONCM_PRIM("filesystem-change-evt-cancel", filesystem_change_evt_cancel, 1, 1, env);
|
||||||
|
|
||||||
GLOBAL_NONCM_PRIM("read", read_f, 0, 1, env);
|
GLOBAL_NONCM_PRIM("read", read_f, 0, 1, env);
|
||||||
GLOBAL_NONCM_PRIM("read/recursive", read_recur_f, 0, 4, env);
|
GLOBAL_NONCM_PRIM("read/recursive", read_recur_f, 0, 4, env);
|
||||||
GLOBAL_NONCM_PRIM("read-syntax", read_syntax_f, 0, 2, env);
|
GLOBAL_NONCM_PRIM("read-syntax", read_syntax_f, 0, 2, env);
|
||||||
|
@ -4319,6 +4327,40 @@ static Scheme_Object *set_port_next_location(int argc, Scheme_Object *argv[])
|
||||||
return scheme_void;
|
return scheme_void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Scheme_Object *filesystem_change_evt(int argc, Scheme_Object *argv[])
|
||||||
|
{
|
||||||
|
Scheme_Object *e;
|
||||||
|
|
||||||
|
if (!SCHEME_PATH_STRINGP(argv[0]))
|
||||||
|
scheme_wrong_contract("filesystem-change-evt", "path-string?", 0, argc, argv);
|
||||||
|
if (argc > 1)
|
||||||
|
scheme_check_proc_arity("filesystem-change-evt", 0, 1, argc, argv);
|
||||||
|
|
||||||
|
e = scheme_filesystem_change_evt(argv[0], 0, (argc < 2));
|
||||||
|
|
||||||
|
if (!e)
|
||||||
|
return _scheme_tail_apply(argv[1], 0, NULL);
|
||||||
|
else
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Scheme_Object *filesystem_change_evt_p(int argc, Scheme_Object **argv)
|
||||||
|
{
|
||||||
|
return (SAME_TYPE(scheme_filesystem_change_evt_type, SCHEME_TYPE(argv[0]))
|
||||||
|
? scheme_true
|
||||||
|
: scheme_false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Scheme_Object *filesystem_change_evt_cancel(int argc, Scheme_Object **argv)
|
||||||
|
{
|
||||||
|
if (!SAME_TYPE(scheme_filesystem_change_evt_type, SCHEME_TYPE(argv[0])))
|
||||||
|
scheme_wrong_contract("filesystem-change-evt-cancel", "filesystem-change-evt?", 0, argc, argv);
|
||||||
|
|
||||||
|
scheme_filesystem_change_evt_cancel(argv[0], NULL);
|
||||||
|
|
||||||
|
return scheme_void;
|
||||||
|
}
|
||||||
|
|
||||||
static intptr_t get_number(Scheme_Object *port, intptr_t pos)
|
static intptr_t get_number(Scheme_Object *port, intptr_t pos)
|
||||||
{
|
{
|
||||||
unsigned char buffer[4];
|
unsigned char buffer[4];
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#define USE_COMPILED_STARTUP 1
|
#define USE_COMPILED_STARTUP 1
|
||||||
|
|
||||||
#define EXPECTED_PRIM_COUNT 1105
|
#define EXPECTED_PRIM_COUNT 1108
|
||||||
#define EXPECTED_UNSAFE_COUNT 100
|
#define EXPECTED_UNSAFE_COUNT 100
|
||||||
#define EXPECTED_FLFXNUM_COUNT 69
|
#define EXPECTED_FLFXNUM_COUNT 69
|
||||||
#define EXPECTED_EXTFL_COUNT 45
|
#define EXPECTED_EXTFL_COUNT 45
|
||||||
|
|
|
@ -3876,6 +3876,12 @@ intptr_t scheme_redirect_get_or_peek_bytes(Scheme_Input_Port *orig_port,
|
||||||
Scheme_Object *unless,
|
Scheme_Object *unless,
|
||||||
Scheme_Schedule_Info *sinfo);
|
Scheme_Schedule_Info *sinfo);
|
||||||
|
|
||||||
|
Scheme_Object *scheme_filesystem_change_evt(Scheme_Object *path, int flags, int report_errs);
|
||||||
|
void scheme_filesystem_change_evt_cancel(Scheme_Object *evt, void *ignored_data);
|
||||||
|
|
||||||
|
int scheme_fd_regular_file(intptr_t fd, int dir_ok);
|
||||||
|
void scheme_check_fd_semaphores(void);
|
||||||
|
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
/* memory debugging */
|
/* memory debugging */
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
consistently.)
|
consistently.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MZSCHEME_VERSION "5.3.900.3"
|
#define MZSCHEME_VERSION "5.3.900.4"
|
||||||
|
|
||||||
#define MZSCHEME_VERSION_X 5
|
#define MZSCHEME_VERSION_X 5
|
||||||
#define MZSCHEME_VERSION_Y 3
|
#define MZSCHEME_VERSION_Y 3
|
||||||
#define MZSCHEME_VERSION_Z 900
|
#define MZSCHEME_VERSION_Z 900
|
||||||
#define MZSCHEME_VERSION_W 3
|
#define MZSCHEME_VERSION_W 4
|
||||||
|
|
||||||
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
|
#define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y)
|
||||||
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)
|
#define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)
|
||||||
|
|
|
@ -209,83 +209,84 @@ enum {
|
||||||
scheme_struct_proc_shape_type, /* 185 */
|
scheme_struct_proc_shape_type, /* 185 */
|
||||||
scheme_phantom_bytes_type, /* 186 */
|
scheme_phantom_bytes_type, /* 186 */
|
||||||
scheme_environment_variables_type, /* 187 */
|
scheme_environment_variables_type, /* 187 */
|
||||||
|
scheme_filesystem_change_evt_type, /* 188 */
|
||||||
|
|
||||||
#ifdef MZTAG_REQUIRED
|
#ifdef MZTAG_REQUIRED
|
||||||
_scheme_last_normal_type_, /* 188 */
|
_scheme_last_normal_type_, /* 189 */
|
||||||
|
|
||||||
scheme_rt_weak_array, /* 189 */
|
scheme_rt_weak_array, /* 190 */
|
||||||
|
|
||||||
scheme_rt_comp_env, /* 190 */
|
scheme_rt_comp_env, /* 191 */
|
||||||
scheme_rt_constant_binding, /* 191 */
|
scheme_rt_constant_binding, /* 192 */
|
||||||
scheme_rt_resolve_info, /* 192 */
|
scheme_rt_resolve_info, /* 193 */
|
||||||
scheme_rt_unresolve_info, /* 193 */
|
scheme_rt_unresolve_info, /* 194 */
|
||||||
scheme_rt_optimize_info, /* 194 */
|
scheme_rt_optimize_info, /* 195 */
|
||||||
scheme_rt_compile_info, /* 195 */
|
scheme_rt_compile_info, /* 196 */
|
||||||
scheme_rt_cont_mark, /* 196 */
|
scheme_rt_cont_mark, /* 197 */
|
||||||
scheme_rt_saved_stack, /* 197 */
|
scheme_rt_saved_stack, /* 198 */
|
||||||
scheme_rt_reply_item, /* 198 */
|
scheme_rt_reply_item, /* 199 */
|
||||||
scheme_rt_closure_info, /* 199 */
|
scheme_rt_closure_info, /* 200 */
|
||||||
scheme_rt_overflow, /* 200 */
|
scheme_rt_overflow, /* 201 */
|
||||||
scheme_rt_overflow_jmp, /* 201 */
|
scheme_rt_overflow_jmp, /* 202 */
|
||||||
scheme_rt_meta_cont, /* 202 */
|
scheme_rt_meta_cont, /* 203 */
|
||||||
scheme_rt_dyn_wind_cell, /* 203 */
|
scheme_rt_dyn_wind_cell, /* 204 */
|
||||||
scheme_rt_dyn_wind_info, /* 204 */
|
scheme_rt_dyn_wind_info, /* 205 */
|
||||||
scheme_rt_dyn_wind, /* 205 */
|
scheme_rt_dyn_wind, /* 206 */
|
||||||
scheme_rt_dup_check, /* 206 */
|
scheme_rt_dup_check, /* 207 */
|
||||||
scheme_rt_thread_memory, /* 207 */
|
scheme_rt_thread_memory, /* 208 */
|
||||||
scheme_rt_input_file, /* 208 */
|
scheme_rt_input_file, /* 209 */
|
||||||
scheme_rt_input_fd, /* 209 */
|
scheme_rt_input_fd, /* 210 */
|
||||||
scheme_rt_oskit_console_input, /* 210 */
|
scheme_rt_oskit_console_input, /* 211 */
|
||||||
scheme_rt_tested_input_file, /* 211 */
|
scheme_rt_tested_input_file, /* 212 */
|
||||||
scheme_rt_tested_output_file, /* 212 */
|
scheme_rt_tested_output_file, /* 213 */
|
||||||
scheme_rt_indexed_string, /* 213 */
|
scheme_rt_indexed_string, /* 214 */
|
||||||
scheme_rt_output_file, /* 214 */
|
scheme_rt_output_file, /* 215 */
|
||||||
scheme_rt_load_handler_data, /* 215 */
|
scheme_rt_load_handler_data, /* 216 */
|
||||||
scheme_rt_pipe, /* 216 */
|
scheme_rt_pipe, /* 217 */
|
||||||
scheme_rt_beos_process, /* 217 */
|
scheme_rt_beos_process, /* 218 */
|
||||||
scheme_rt_system_child, /* 218 */
|
scheme_rt_system_child, /* 219 */
|
||||||
scheme_rt_tcp, /* 219 */
|
scheme_rt_tcp, /* 220 */
|
||||||
scheme_rt_write_data, /* 220 */
|
scheme_rt_write_data, /* 221 */
|
||||||
scheme_rt_tcp_select_info, /* 221 */
|
scheme_rt_tcp_select_info, /* 222 */
|
||||||
scheme_rt_param_data, /* 222 */
|
scheme_rt_param_data, /* 223 */
|
||||||
scheme_rt_will, /* 223 */
|
scheme_rt_will, /* 224 */
|
||||||
scheme_rt_linker_name, /* 224 */
|
scheme_rt_linker_name, /* 225 */
|
||||||
scheme_rt_param_map, /* 225 */
|
scheme_rt_param_map, /* 226 */
|
||||||
scheme_rt_finalization, /* 226 */
|
scheme_rt_finalization, /* 227 */
|
||||||
scheme_rt_finalizations, /* 227 */
|
scheme_rt_finalizations, /* 228 */
|
||||||
scheme_rt_cpp_object, /* 228 */
|
scheme_rt_cpp_object, /* 229 */
|
||||||
scheme_rt_cpp_array_object, /* 229 */
|
scheme_rt_cpp_array_object, /* 230 */
|
||||||
scheme_rt_stack_object, /* 230 */
|
scheme_rt_stack_object, /* 231 */
|
||||||
scheme_rt_preallocated_object, /* 231 */
|
scheme_rt_preallocated_object, /* 232 */
|
||||||
scheme_thread_hop_type, /* 232 */
|
scheme_thread_hop_type, /* 233 */
|
||||||
scheme_rt_srcloc, /* 233 */
|
scheme_rt_srcloc, /* 234 */
|
||||||
scheme_rt_evt, /* 234 */
|
scheme_rt_evt, /* 235 */
|
||||||
scheme_rt_syncing, /* 235 */
|
scheme_rt_syncing, /* 236 */
|
||||||
scheme_rt_comp_prefix, /* 236 */
|
scheme_rt_comp_prefix, /* 237 */
|
||||||
scheme_rt_user_input, /* 237 */
|
scheme_rt_user_input, /* 238 */
|
||||||
scheme_rt_user_output, /* 238 */
|
scheme_rt_user_output, /* 239 */
|
||||||
scheme_rt_compact_port, /* 239 */
|
scheme_rt_compact_port, /* 240 */
|
||||||
scheme_rt_read_special_dw, /* 240 */
|
scheme_rt_read_special_dw, /* 241 */
|
||||||
scheme_rt_regwork, /* 241 */
|
scheme_rt_regwork, /* 242 */
|
||||||
scheme_rt_rx_lazy_string, /* 242 */
|
scheme_rt_rx_lazy_string, /* 243 */
|
||||||
scheme_rt_buf_holder, /* 243 */
|
scheme_rt_buf_holder, /* 244 */
|
||||||
scheme_rt_parameterization, /* 244 */
|
scheme_rt_parameterization, /* 245 */
|
||||||
scheme_rt_print_params, /* 245 */
|
scheme_rt_print_params, /* 246 */
|
||||||
scheme_rt_read_params, /* 246 */
|
scheme_rt_read_params, /* 247 */
|
||||||
scheme_rt_native_code, /* 247 */
|
scheme_rt_native_code, /* 248 */
|
||||||
scheme_rt_native_code_plus_case, /* 248 */
|
scheme_rt_native_code_plus_case, /* 249 */
|
||||||
scheme_rt_jitter_data, /* 249 */
|
scheme_rt_jitter_data, /* 250 */
|
||||||
scheme_rt_module_exports, /* 250 */
|
scheme_rt_module_exports, /* 251 */
|
||||||
scheme_rt_delay_load_info, /* 251 */
|
scheme_rt_delay_load_info, /* 252 */
|
||||||
scheme_rt_marshal_info, /* 252 */
|
scheme_rt_marshal_info, /* 253 */
|
||||||
scheme_rt_unmarshal_info, /* 253 */
|
scheme_rt_unmarshal_info, /* 254 */
|
||||||
scheme_rt_runstack, /* 254 */
|
scheme_rt_runstack, /* 255 */
|
||||||
scheme_rt_sfs_info, /* 255 */
|
scheme_rt_sfs_info, /* 256 */
|
||||||
scheme_rt_validate_clearing, /* 256 */
|
scheme_rt_validate_clearing, /* 257 */
|
||||||
scheme_rt_avl_node, /* 257 */
|
scheme_rt_avl_node, /* 258 */
|
||||||
scheme_rt_lightweight_cont, /* 258 */
|
scheme_rt_lightweight_cont, /* 259 */
|
||||||
scheme_rt_export_info, /* 259 */
|
scheme_rt_export_info, /* 260 */
|
||||||
scheme_rt_cont_jmp, /* 260 */
|
scheme_rt_cont_jmp, /* 261 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_scheme_last_type_
|
_scheme_last_type_
|
||||||
|
|
|
@ -3480,8 +3480,10 @@ Scheme_Object *scheme_fd_to_semaphore(intptr_t fd, int mode, int is_socket)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
# ifdef HAVE_KQUEUE_SYSCALL
|
# ifdef HAVE_KQUEUE_SYSCALL
|
||||||
if (!is_socket)
|
if (!is_socket) {
|
||||||
return NULL; /* kqueue() might not work on devices, such as ttys */
|
if (!scheme_fd_regular_file(fd, 10))
|
||||||
|
return NULL; /* kqueue() might not work on devices, such as ttys */
|
||||||
|
}
|
||||||
if (scheme_semaphore_fd_kqueue < 0) {
|
if (scheme_semaphore_fd_kqueue < 0) {
|
||||||
scheme_semaphore_fd_kqueue = kqueue();
|
scheme_semaphore_fd_kqueue = kqueue();
|
||||||
if (scheme_semaphore_fd_kqueue < 0) {
|
if (scheme_semaphore_fd_kqueue < 0) {
|
||||||
|
@ -3504,6 +3506,7 @@ Scheme_Object *scheme_fd_to_semaphore(intptr_t fd, int mode, int is_socket)
|
||||||
v = scheme_hash_get(scheme_semaphore_fd_mapping, key);
|
v = scheme_hash_get(scheme_semaphore_fd_mapping, key);
|
||||||
if (!v && ((mode == MZFD_CHECK_READ)
|
if (!v && ((mode == MZFD_CHECK_READ)
|
||||||
|| (mode == MZFD_CHECK_WRITE)
|
|| (mode == MZFD_CHECK_WRITE)
|
||||||
|
|| (mode == MZFD_CHECK_VNODE)
|
||||||
|| (mode == MZFD_REMOVE)))
|
|| (mode == MZFD_REMOVE)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -3529,13 +3532,14 @@ Scheme_Object *scheme_fd_to_semaphore(intptr_t fd, int mode, int is_socket)
|
||||||
scheme_hash_set(scheme_semaphore_fd_mapping, key, NULL);
|
scheme_hash_set(scheme_semaphore_fd_mapping, key, NULL);
|
||||||
# ifdef HAVE_KQUEUE_SYSCALL
|
# ifdef HAVE_KQUEUE_SYSCALL
|
||||||
{
|
{
|
||||||
GC_CAN_IGNORE struct kevent kev[2];
|
GC_CAN_IGNORE struct kevent kev[3];
|
||||||
struct timespec timeout = {0, 0};
|
struct timespec timeout = {0, 0};
|
||||||
int kr;
|
int kr;
|
||||||
EV_SET(kev, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
|
EV_SET(kev, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
|
||||||
EV_SET(&kev[1], fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
|
EV_SET(&kev[1], fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
|
||||||
|
EV_SET(&kev[2], fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
|
||||||
do {
|
do {
|
||||||
kr = kevent(scheme_semaphore_fd_kqueue, kev, 2, NULL, 0, &timeout);
|
kr = kevent(scheme_semaphore_fd_kqueue, kev, 3, NULL, 0, &timeout);
|
||||||
} while ((kr == -1) && (errno == EINTR));
|
} while ((kr == -1) && (errno == EINTR));
|
||||||
log_kqueue_error("remove", kr);
|
log_kqueue_error("remove", kr);
|
||||||
}
|
}
|
||||||
|
@ -3552,10 +3556,13 @@ Scheme_Object *scheme_fd_to_semaphore(intptr_t fd, int mode, int is_socket)
|
||||||
# endif
|
# endif
|
||||||
s = NULL;
|
s = NULL;
|
||||||
} else if ((mode == MZFD_CHECK_READ)
|
} else if ((mode == MZFD_CHECK_READ)
|
||||||
|| (mode == MZFD_CREATE_READ)) {
|
|| (mode == MZFD_CREATE_READ)
|
||||||
|
|| (mode == MZFD_CHECK_VNODE)
|
||||||
|
|| (mode == MZFD_CREATE_VNODE)) {
|
||||||
s = SCHEME_VEC_ELS(v)[0];
|
s = SCHEME_VEC_ELS(v)[0];
|
||||||
if (SCHEME_FALSEP(s)) {
|
if (SCHEME_FALSEP(s)) {
|
||||||
if (mode == MZFD_CREATE_READ) {
|
if ((mode == MZFD_CREATE_READ)
|
||||||
|
|| (mode == MZFD_CREATE_VNODE)) {
|
||||||
s = scheme_make_sema(0);
|
s = scheme_make_sema(0);
|
||||||
SCHEME_VEC_ELS(v)[0] = s;
|
SCHEME_VEC_ELS(v)[0] = s;
|
||||||
# ifdef HAVE_KQUEUE_SYSCALL
|
# ifdef HAVE_KQUEUE_SYSCALL
|
||||||
|
@ -3563,7 +3570,13 @@ Scheme_Object *scheme_fd_to_semaphore(intptr_t fd, int mode, int is_socket)
|
||||||
GC_CAN_IGNORE struct kevent kev;
|
GC_CAN_IGNORE struct kevent kev;
|
||||||
struct timespec timeout = {0, 0};
|
struct timespec timeout = {0, 0};
|
||||||
int kr;
|
int kr;
|
||||||
EV_SET(&kev, fd, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, NULL);
|
if (mode == MZFD_CREATE_READ)
|
||||||
|
EV_SET(&kev, fd, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, NULL);
|
||||||
|
else
|
||||||
|
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT,
|
||||||
|
(NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND
|
||||||
|
| NOTE_RENAME | NOTE_ATTRIB),
|
||||||
|
0, NULL);
|
||||||
do {
|
do {
|
||||||
kr = kevent(scheme_semaphore_fd_kqueue, &kev, 1, NULL, 0, &timeout);
|
kr = kevent(scheme_semaphore_fd_kqueue, &kev, 1, NULL, 0, &timeout);
|
||||||
} while ((kr == -1) && (errno == EINTR));
|
} while ((kr == -1) && (errno == EINTR));
|
||||||
|
@ -3586,7 +3599,8 @@ Scheme_Object *scheme_fd_to_semaphore(intptr_t fd, int mode, int is_socket)
|
||||||
} else
|
} else
|
||||||
s = NULL;
|
s = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else if ((mode == MZFD_CHECK_WRITE)
|
||||||
|
|| (mode == MZFD_CREATE_WRITE)) {
|
||||||
s = SCHEME_VEC_ELS(v)[1];
|
s = SCHEME_VEC_ELS(v)[1];
|
||||||
if (SCHEME_FALSEP(s)) {
|
if (SCHEME_FALSEP(s)) {
|
||||||
if (mode == MZFD_CREATE_WRITE) {
|
if (mode == MZFD_CREATE_WRITE) {
|
||||||
|
@ -3650,7 +3664,7 @@ static int check_fd_semaphores()
|
||||||
key = scheme_make_integer_value(kev.ident);
|
key = scheme_make_integer_value(kev.ident);
|
||||||
v = scheme_hash_get(scheme_semaphore_fd_mapping, key);
|
v = scheme_hash_get(scheme_semaphore_fd_mapping, key);
|
||||||
if (v) {
|
if (v) {
|
||||||
if (kev.filter == EVFILT_READ) {
|
if ((kev.filter == EVFILT_READ) || (kev.filter == EVFILT_VNODE)) {
|
||||||
s = SCHEME_VEC_ELS(v)[0];
|
s = SCHEME_VEC_ELS(v)[0];
|
||||||
if (!SCHEME_FALSEP(s)) {
|
if (!SCHEME_FALSEP(s)) {
|
||||||
scheme_post_sema_all(s);
|
scheme_post_sema_all(s);
|
||||||
|
@ -3849,6 +3863,11 @@ static int check_fd_semaphores()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scheme_check_fd_semaphores(void)
|
||||||
|
{
|
||||||
|
(void)check_fd_semaphores();
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int running;
|
int running;
|
||||||
double sleep_end;
|
double sleep_end;
|
||||||
|
|
|
@ -209,6 +209,7 @@ scheme_init_type ()
|
||||||
set_name(scheme_struct_type_type, "<struct-type>");
|
set_name(scheme_struct_type_type, "<struct-type>");
|
||||||
set_name(scheme_listener_type, "<tcp-listener>");
|
set_name(scheme_listener_type, "<tcp-listener>");
|
||||||
set_name(scheme_tcp_accept_evt_type, "<tcp-accept-evt>");
|
set_name(scheme_tcp_accept_evt_type, "<tcp-accept-evt>");
|
||||||
|
set_name(scheme_filesystem_change_evt_type, "<filesystem-change-evt>");
|
||||||
set_name(scheme_namespace_type, "<namespace>");
|
set_name(scheme_namespace_type, "<namespace>");
|
||||||
set_name(scheme_config_type, "<parameterization>");
|
set_name(scheme_config_type, "<parameterization>");
|
||||||
set_name(scheme_will_executor_type, "<will-executor>");
|
set_name(scheme_will_executor_type, "<will-executor>");
|
||||||
|
@ -613,7 +614,7 @@ void scheme_register_traversers(void)
|
||||||
GC_REG_TRAV(scheme_unix_path_type, bstring_obj);
|
GC_REG_TRAV(scheme_unix_path_type, bstring_obj);
|
||||||
GC_REG_TRAV(scheme_windows_path_type, bstring_obj);
|
GC_REG_TRAV(scheme_windows_path_type, bstring_obj);
|
||||||
GC_REG_TRAV(scheme_symbol_type, symbol_obj);
|
GC_REG_TRAV(scheme_symbol_type, symbol_obj);
|
||||||
#ifdef MZ_USE_PLACES
|
#ifdef MZ_USE_PLACES
|
||||||
GC_REG_TRAV(scheme_serialized_symbol_type, bstring_obj);
|
GC_REG_TRAV(scheme_serialized_symbol_type, bstring_obj);
|
||||||
GC_REG_TRAV(scheme_serialized_keyword_type, bstring_obj);
|
GC_REG_TRAV(scheme_serialized_keyword_type, bstring_obj);
|
||||||
GC_REG_TRAV(scheme_place_dead_type, small_object);
|
GC_REG_TRAV(scheme_place_dead_type, small_object);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user