97jaz / gregor

Date and time library for Racket
45 stars 10 forks source link

"zoneinfo-data.rkt: no such file" error with `dynamic-rerequire` #1

Closed mbutterick closed 9 years ago

mbutterick commented 9 years ago

I’m on OS X. I see from the tzinfo source that tzinfo-data.rkt represents a file on Windows, and that it’s wrapped in with-handlers so you get #f if the file isn’t found. But when a source file with (require gregor) is loaded with dynamic-rerequire, this exception handler is circumvented, and the file not found error surfaces, as shown below.

Test case requires two files:

boom.rkt:

#lang racket/base
(require gregor)

fuse.rkt:

#lang racket/base
(require racket/rerequire)
(dynamic-rerequire (string->path "boom.rkt"))

For me, running fuse.rkt raises the error:

get-module-code: no such file: #<path:/Users/MB/git/racket/racket/share/pkgs/
tzinfo/tzinfo/zoneinfo-data.rkt>
97jaz commented 9 years ago

I'll look into this tonight. My initial impression is that I'm surprised the exception handler doesn't work here. I wonder if a different exception is raised.

97jaz commented 9 years ago

And there's probably a way to do this w/o using an exception handler at all.

mbutterick commented 9 years ago

IIUC dynamic-rerequire wants to track modification dates for all transitively loaded modules. So my theory here is that dynamic-rerequire somehow 1) notices the module name within dynamic-require, 2) manages to preempt the with-handlers around it, 3) throws an error when it tries to get the modification date of the nonexistent module.

After some fiddling, I found that changing the implicit file check via with-handlers to an explicit check via file-exists? eliminated the error. I’m not warranting that this solution plays nicely with the rest of your code, but it might be a point of departure:

From this:

(define ZONEINFO-DATA
  (with-handlers ([exn:fail:filesystem? (lambda _ #f)])
    (dynamic-require 'tzinfo/zoneinfo-data 'ZONEINFO-DATA)))

to this:

(define ZONEINFO-DATA
  (let ([mod-name 'tzinfo/zoneinfo-data])
    (local-require syntax/modresolve)
    (and (file-exists? (resolve-module-path mod-name (current-directory)))
         (dynamic-require mod-name 'ZONEINFO-DATA))))
97jaz commented 9 years ago

An explicit test is preferable to an exception handler. Thanks!

97jaz commented 9 years ago

Fixed in tzinfo master.

samth commented 9 years ago

It may be that you may have wanted to use define-runtime-module-path-index here to make the original code work correctly

97jaz commented 9 years ago

@samth Does that explain the behavior we were seeing? The code in question was set up to handle exn:fail:filesystem, and although we were seeing a "no such file" error message, the exception handler was never being executed.

So, the problem wasn't that we had the wrong path (though there may very well have been more than one problem); it's that the code to handle the case where we can't find the file wasn't being invoked.

I didn't investigate very far, because I preferred not to use an exception handler here, at all.

samth commented 9 years ago

My guess is that dynamic-rerequire didn't know that the file was relevant, which led to some other error somewhere.