Loop of restore previous files craziness

This happened in class today.

I created a small file that exports some stuff and renames signatures from deinprogramm/sdp/image.rkt to match the upper-case style that BSL uses.

Things seemed to be working okay (except that students are so used to Chromebooks and saving stuff in the cloud that they don't understand what "Save the file in the same folder as your file, and make sure you've saved your file, so that DrRacket knows what it is, and no 'apcsp (1).rkt' is not the same name as 'apcsp.rkt', etc.), except that today I asked them to update the file.

Several students (and I) had our computers go into an endless loop where we'd run the main file that had (require "apcsp.rkt") and DrRacket would ask if we wanted to restore files from the previous session, would open a new window, and then do weird things like run out of memory or just say that Interactions was disabled.

The only thing I could think was that maybe an old version of apcsp.rkt was hanging around and DrRacket thought it was an auto-saved file, but I couldn't figure out what was happening.

Any ideas what might be going on? I know the way to actually deal with this is to package up the file so that the require could depend on a package version, and I'm hoping to do that soon, but haven't gotten around to it, yet.

1 Like

let me know if I understand this

  • you are using deinprogramm
  • your program includes (require "apcsp.rkt")
  • you run your program
  • DrRacket triggers 'restore files' dialog, then crashes

It sounds like "apcsp.rkt" has a (require drracket) or similar that calls DrRacket from inside DrRacket

Can you share "apcsp.rkt"?

Best
Stephen :beetle:

The apcsp.rkt file looks like this:

#lang racket
(require deinprogramm/signature/signature-syntax
         deinprogramm/signature/signature
         deinprogramm/signature/signature-english
         2htdp/image
         2htdp/universe
         lang/posn
         rackunit)

(provide ε let Image Color
         Mode XPlace YPlace Angle PulledPoint
         SideCount StepCount Posn Pen PenStyle PenCap PenJoin
         (all-from-out 2htdp/image 2htdp/universe))

(define ε 0.000000000001)

; deinprogramm/sdp/image.rkt
(define Image (signature Image (predicate image?)))
(define Color (signature Color (predicate image-color?)))
(define Mode (signature Mode (predicate mode?)))
(define YPlace (signature YPlace (predicate y-place?)))
(define XPlace (signature XPlace (predicate x-place?)))
(define Angle (signature Angle (predicate angle?)))
(define PulledPoint (signature PulledPoint (predicate pulled-point?)))
(define SideCount (signature SideCount (predicate side-count?)))
(define StepCount (signature StepCount (predicate step-count?)))
(define Posn (signature Posn (predicate real-valued-posn?)))
(define Pen (signature Pen (predicate pen?)))
(define PenStyle (signature PenStyle (predicate pen-style?)))
(define PenCap (signature PenCap (predicate pen-cap?)))
(define PenJoin (signature PenJoin (predicate pen-join?)))
; deinprogramm/sdp/universe.rkt
(define MouseEvent
    (signature MouseEvent
      (enum "button-down" "button-up" "drag" "move" "enter" "leave")))
  (define PadEvent
    (signature PadEvent
      (enum "left" "right" "up" "down" "w" "s" "a" "d" " " "shift" "rshift")))

Students had downloaded and used this file for a while. I then added the line

(print-boolean-long-form #f)

after the require and before the provide to get #t and #f instead of #true and #false. It's entirely possible that I'm doing that wrong, because I've never tried to set a parameter, before.

When I did that and asked students to replace the old apcsp.rkt with the new one, every time they ran a file that had (require "apcsp.rkt") in it, DrRacket would ask if they wanted to restore files from the previous session, and no matter what you responded with, a new file would open and the file that you'd clicked Run in would say that execution had halted.

I can't reproduce it on my home computer, can't find any auto-saved files (other places, besides the home folder and the folder where the student's file is saved, I should look for them, btw?), and even creating a brand new folder and opening from there sometimes causes the problem.

I'm a little stumped. I guess the next thing to try is to delete ~/.config/racket folder and see if that fixes anything. If I can reproduce the error again, I'll try to post a video.

Todd

OK. I have a screencast of what is going on. Student clicks Run on short file that requires apcsp.rkt. DrRacket asks if she wants to restore previous files. No matter what she clicks, a new file gets opened and she gets the error "Evaluation thread is no longer running." When she goes back to the original file, Interactions are disabled.

I've seen this on MacOS, Windows, and Linux. I've looked for hidden files in the directories and deleted them. I've deleted the compiled folder. I can't figure out what is going on, but it's driving me crazy.

Help!

Watching the video it seems likely that @stde-epro has correctly diagnosed the problem. As DrRacket is itself written in Racket, you can run it inside itself, so it really looks like we're seeing the inner one start up in the video.

That said, when I do what you're doing with the apscp.rkt file you posted, I don't see the same behavior. Is it possible that there is another require that got inserted somewhere? If not, maybe there is some other piece of the puzzle we're missing?

If you're up for some debugging, then we can add some printfs into the function that shows the autosave dialog to find out how it is being called and maybe that'll shed some light. Specifically, open up the file (use cmd-shift-o) framework/private/autosave and at the top of the function restore-autosave-files/gui put these lines:

  (define (restore-autosave-files/gui [table #f])
    (printf "restore-autosave-files/gui called\n")
    (for ([x (in-list (continuation-mark-set->context
                       (current-continuation-marks)))])
      (printf "  ~s\n" x))
    .... rest of the function goes here, as it was before

then we'll be able to see how we're getting to the autosave dialog and maybe that'll give us a hint how the inner drracket is getting started.

OK. For some reason it stopped doing it on my computer, so I need to get it started again or figure out how to do this on a student's laptop. Stay tuned.

Welp, now I've broken my DrRacket:

default-load-handler: expected a `module' declaration, but found something else
file: /usr/share/racket/pkgs/gui-lib/framework/private/autosave.rkt
context...:
body of "/usr/share/racket/pkgs/drracket-core-lib/drracket/private/drracket-normal.rkt"
body of "/usr/share/racket/pkgs/drracket-core-lib/drracket/drracket.rkt"

Here's what the top of that function looks like now:

 ;; restore-autosave-files/gui : -> void?
  ;; opens a frame that lists the autosave files that have changed.
  (define (restore-autosave-files/gui [table #f])
    (printf "restore-autosave-files/gui called\n")
    (for ([x (in-list (continuation-mark-set->context
                       (current-continuation-marks)))])
      (printf "  ~s\n" x))
    (cond
      [table (restore-autosave-files/gui/table table)]
      [else
       (define toc-path (current-toc-path))
       (when (file-exists? toc-path)
         ;; Load table from file, and check that the file was not corrupted
         (define raw-read-table

Did I miscopy something?

I don't see anything obvious in the snippet, but is it possible you put a stray letter at the top of the file?

That's what I must have done.

Here's the print-out from that after a re-install:

  (restore-autosave-files/gui . #(struct:srcloc #<path:/usr/share/racket/pkgs/gui-lib/framework/private/autosave.rkt> 135 2 4931 1374))
  (#f . #(struct:srcloc ".../private/arrow-val-first.rkt" 489 18 20850 36))
  (#f . #(struct:srcloc ".../unit/lang.rkt" 84 9 3255 43))
  (#f . #(struct:srcloc #<path:/usr/share/racket/pkgs/drracket-core-lib/drracket/private/link.rkt> 57 0 1563 1675))
  (|body of "/usr/share/racket/pkgs/drracket-core-lib/drracket/tool-lib.rkt"| . #f)
  (#f . #(struct:srcloc #<path:/usr/share/racket/pkgs/drracket-core-lib/drracket/private/stack-checkpoint.rkt> 114 30 4721 131))
  (call-with-exception-handler . #(struct:srcloc #<path:/usr/share/racket/collects/racket/private/more-scheme.rkt> 266 2 9251 256))
  (*init . #(struct:srcloc #<path:/usr/share/racket/pkgs/drracket-core-lib/drracket/private/module-language.rkt> 481 8 23009 762))
  (call-with-break-parameterization . #(struct:srcloc #<path:/usr/share/racket/collects/racket/private/more-scheme.rkt> 148 2 4909 517))
  (#f . #(struct:srcloc #<path:/usr/share/racket/pkgs/drracket-core-lib/drracket/private/rep.rkt> 1193 9 49642 5063))
  (#f . #(struct:srcloc #<path:/usr/share/racket/pkgs/drracket-core-lib/drracket/private/rep.rkt> 1490 15 63849 1548))
  (#f . #(struct:srcloc #<path:/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt> 436 6 19103 1056))
  (#f . #(struct:srcloc #<path:/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt> 487 32 21090 120))
  (call-with-break-parameterization . #(struct:srcloc #<path:/usr/share/racket/collects/racket/private/more-scheme.rkt> 148 2 4909 517))
  (eventspace-handler-thread-proc . #(struct:srcloc #<path:/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt> 371 11 16551 690))

This looks to me like there is a a (require drracket/tool-lib) coming from somewhere. Still not seeing exactly where, tho!

As some help decoding the stacktrace, this portion of it (the lower part):

  (call-with-exception-handler . #(struct:srcloc #<path:/usr/share/racket/collects/racket/private/more-scheme.rkt> 266 2 9251 256))
  (*init . #(struct:srcloc #<path:/usr/share/racket/pkgs/drracket-core-lib/drracket/private/module-language.rkt> 481 8 23009 762))
  (call-with-break-parameterization . #(struct:srcloc #<path:/usr/share/racket/collects/racket/private/more-scheme.rkt> 148 2 4909 517))
  (#f . #(struct:srcloc #<path:/usr/share/racket/pkgs/drracket-core-lib/drracket/private/rep.rkt> 1193 9 49642 5063))
  (#f . #(struct:srcloc #<path:/usr/share/racket/pkgs/drracket-core-lib/drracket/private/rep.rkt> 1490 15 63849 1548))
  (#f . #(struct:srcloc #<path:/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt> 436 6 19103 1056))
  (#f . #(struct:srcloc #<path:/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt> 487 32 21090 120))
  (call-with-break-parameterization . #(struct:srcloc #<path:/usr/share/racket/collects/racket/private/more-scheme.rkt> 148 2 4909 517))
  (eventspace-handler-thread-proc . #(struct:srcloc #<path:/usr/share/racket/pkgs/gui-lib/mred/private/wx/common/queue.rkt> 371 11 16551 690))

looks to me like the code that is evaluating a program for the user and is ligit. That is, you get to *init, whose source code is here and then you get to the call-with-exception-handler which is probably what one of the things in the body of that function expands into and then the next thing is running drracket/tool-lib which suggests that something is requiring it.

Maybe a good next step is to add a few more printfs, changing this:

(define (*init)
  (parameterize ([current-namespace (current-namespace)])
    ;; the prompt makes it continue after an error
    (call-with-continuation-prompt
     (λ () (with-stack-checkpoint 
               (begin
                 (*do-module-specified-configuration)
                 (namespace-require modspec)
                 (for ([submod (in-list (module-language-settings-submodules-to-run settings))])
                   (define submod-spec `(submod ,modspec ,@submod))
                   (when (module-declared? submod-spec)
                     (dynamic-require submod-spec #f))))))))
  (current-namespace (module->namespace modspec))
  (check-interactive-language))

into this

(define (*init)
  (oprintf "1\n")
  (parameterize ([current-namespace (current-namespace)])
    ;; the prompt makes it continue after an error
    (call-with-continuation-prompt
     (λ () (with-stack-checkpoint 
               (begin
                 (oprintf "2\n")
                 (*do-module-specified-configuration)
                 (oprintf "3 ~s\n" modspec)
                 (namespace-require modspec)
                 (for ([submod (in-list (module-language-settings-submodules-to-run settings))])
                   (oprintf "4 ~s\n" submod)
                   (define submod-spec `(submod ,modspec ,@submod))
                   (when (module-declared? submod-spec)
                     (dynamic-require submod-spec #f))))))))
  (oprintf "5\n")
  (current-namespace (module->namespace modspec))
  (oprintf "6\n")
  (check-interactive-language))

and maybe that output'll give me a hint that'll suggest something more useful ...

1
2
3 'anonymous-module
4 (test)
4 (main)
5
6

Is that at all helpful?

Which part of the printouts were present when the dialog appeared and which parts of the printouts were after the dialog appeared? (Or are you saying it all showed up before the dialog did?)

Oh. I didn't check. Hang on.

They all appeared after the restore files dialog.

I can't tell if they're before or after the new window opens. (It blocks the previous window.) But the lines are there either before or soon after the new window opens.

Oh, wait! I'm an idiot.

I had multiple versions of "apcsp.rkt" and one of them had drracket/tool-lib in the require list.

I don't know why I added it or when.

I'm so sorry to have wasted your time!

1 Like

Yay! I'm glad you figured it out!

1 Like

OK. I have deleted every copy except one of the file and I'm going to use symbolic links from now on so I don't have to worry about multiple versions. (Except, of course, the ones the students have downloaded to their own machines, which will continue to vex me.)

THANK YOU AGAIN!

I think I was trying to set the syntactic coverage setting, only to realize it couldn't be done and then forgot to remove the require.

1 Like