This is an archive of the discontinued Mercurial Phabricator instance.

worker: use one pipe per posix worker and select() in parent process
ClosedPublic

Authored by hooper on Jul 17 2018, 6:44 PM.

Details

Summary

This allows us to pass results larger than PIPE_BUF through the pipes without
interleaving them. This is necessary now because "hg fix" sends file contents
as the result from workers.

Diff Detail

Repository
rHG Mercurial
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.

Event Timeline

hooper created this revision.Jul 17 2018, 6:44 PM
yuja added a subscriber: yuja.Jul 18 2018, 7:37 AM

@@ -138,7 +138,15 @@

oldchldhandler = signal.signal(signal.SIGCHLD, sigchldhandler)
ui.flush()
parentpid = os.getpid()

+ pipes = []

for pargs in partition(args, workers):

+ # Every worker gets its own pipe to send results on, so we don't have to
+ # implement atomic writes larger than PIPE_BUF. Each forked process has
+ # its own pipe's descriptors in the local variables, and the parent
+ # process has the full list of pipe descriptors (and it doesn't really
+ # care what order they're in).
+ rfd, wfd = os.pipe()
+ pipes.append((rfd, wfd))

  1. make sure we use os._exit in all worker code paths. otherwise the
  2. worker may do some clean-ups which could cause surprises like
  3. deadlock. see sshpeer.cleanup for example.

@@ -175,8 +183,10 @@

        finally:
            os._exit(ret & 255)
pids.add(pid)
  • os.close(wfd)
  • fp = os.fdopen(rfd, r'rb', 0)

+ fps = []
+ for rfd, wfd in pipes:
+ os.close(wfd)
+ fps.append(os.fdopen(rfd, r'rb', 0))

This isn't enough. For child processes, all pipe fds except for the last
wfd have to be closed at the beginning of workerfunc().

+ rlist, wlist, xlist = select.select(fps, [], fps)

Can you rewrite it to use the selectors module? commandserver.py has an
example.

hooper updated this revision to Diff 9626.Jul 18 2018, 2:45 PM

Do you want to move the selector import stuff to pycompat?

yuja added a comment.Jul 19 2018, 8:15 AM

Queued, thanks. We'll probably need selector.close() somewhere.

Do you want to move the selector import stuff to pycompat?

Sounds nice. We'll have to pull the latest selectors2 module to get rid of
reference cycle. The issue addressed by a568a46751b6 appears to be fixed
in upstream.

This revision was automatically updated to reflect the committed changes.