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.

Reply via email to