At Fri, 14 Jun 2019 15:26:17 -0700, Matthew Butterick wrote: > > > > On Jun 13, 2019, at 6:43 PM, Matthew Flatt <mfl...@cs.utah.edu> wrote: > > > > > > Oh, don't do that. Unreliable workarounds to concurrency problems > > really do come back to bite you later. > > To ask the second dumbest possible question, what error-recovery policies are > reliable under concurrency? (Put another way, what guarantees exist about > errors under concurrency? E.g. can we trust that all errors will trigger an > exception?) > > And the dumbest possible: if there are no such policies, then how can you > ever > be certain the code works?
That's a difficult and non-dumb question, and what follows is probably too general of an answer, but I'll try. Concurrency with shared state is a particularly rich source of unspecified behavior. The only way to deal with that is to make sure your program never reaches an unspecified situation. If concurrently reading and writing to a shared mutable variable is not specified, for example, then one way to avoid that is by using a lock (whose behavior with concurrency is specified) and only touch the variable while holding the lock. And if your program does reach an unspecified situation? Normally you do not get an error; some difficulty in detecting the error is probably why it's unspecified in the first place. But I think you're more interested in the filesystem level. The range of possible behaviors is usually more specified at the filesystem level, but it's not always easy to reason about. For example, `rename-file-or-directory` is an atomic operation on Unix filesystems, which means that if two processes concurrently try to rename different files to the same path, then one of them will win; the resulting path will refer to one file or the other with its contents intact, and the other file's content will effectively disappear. That's enough specification to be useful for some tasks, and other tasks just shouldn't enable those kinds of races. And then there's Windows, where `rename-file-or-directory` is not straightforwardly atomic. Meanwhile, errors such as "permission denied" can be reported for things that you would not consider to be permission errors, like moving a file to a name that was formerly occupied, but that was deleted while some process still has it open, so the name is not yet released. So, as a practical matter, the set of behaviors to avoid is larger. The errors that are possible from filesystem operations are usually pretty open-ended, especially at the Racket level, where we don't try to enumerate them. Meanwhile, you usually get some integrity guarantees from the filesystem, though we don't try to enumerate those exhaustively in the Racket documentation, either. Sometimes, staying out of the error-triggering space is unavoidable, and the possible errors are well enough defined by all filesystems, so retrying is a workable solution. If you really have to be in that space, then retry an arbitrary number of times, perhaps with an exponential backoff (i.e., double the delay between retries). -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/5d042f03.1c69fb81.f1a05.491dSMTPIN_ADDED_MISSING%40gmr-mx.google.com. For more options, visit https://groups.google.com/d/optout.