SIGQUIT debugging breaks networking because httplib (and others?) don't handle EINTR properly

Bug #173007 reported by Michael Hudson-Doyle
4
Affects Status Importance Assigned to Milestone
Bazaar
Confirmed
Wishlist
Unassigned

Bug Description

If you're wondering why your branch over http: is going terribly slowly, you can type C-\ to break into pdb, but when you type 'c' to continue the http networking layer will die with an interrupted system call:

Traceback (most recent call last):
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/commands.py", line 802, in run_bzr_catch_errors
    return run_bzr(argv)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/commands.py", line 758, in run_bzr
    ret = run(*run_argv)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/commands.py", line 492, in run_argv_aliases
    return self.run(**all_cmd_args)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/builtins.py", line 893, in run
    possible_transports=[to_transport])
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/bzrdir.py", line 829, in sprout
    revision_id=revision_id)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/decorators.py", line 127, in read_locked
    return unbound(self, *args, **kwargs)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/repository.py", line 960, in sprout
    dest_repo.fetch(self, revision_id=revision_id)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/repository.py", line 873, in fetch
    return inter.fetch(revision_id=revision_id, pb=pb, find_ghosts=find_ghosts)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/decorators.py", line 165, in write_locked
    return unbound(self, *args, **kwargs)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/repository.py", line 2468, in fetch
    pb=pb)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/fetch.py", line 103, in __init__
    self.__fetch()
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/fetch.py", line 132, in __fetch
    self._fetch_everything_for_revisions(revs, pp)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/fetch.py", line 150, in _fetch_everything_for_revisions
    for knit_kind, file_id, revisions in data_to_fetch:
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/repository.py", line 1368, in item_keys_introduced_by
    file_ids = self.fileids_altered_by_revision_ids(revision_ids)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/repository.py", line 1214, in fileids_altered_by_revision_ids
    selected_revision_ids)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/repository.py", line 1192, in _find_file_ids_from_xml_inventory_lines
    line_iterator).iterkeys():
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/repository.py", line 1132, in _find_text_key_references_from_xml_inventory_lines
    for line, version_id in line_iterator:
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/knit.py", line 1140, in iter_lines_added_or_present_in_versions
    enumerate(self._data.read_records_iter(version_id_records)):
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/knit.py", line 2226, in read_records_iter
    izip(iter(needed_records), raw_data):
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/knit.py", line 1934, in get_raw_records
    for pos, data in self._transport.readv(self._filename, read_vector):
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/transport/http/__init__.py", line 270, in _readv
    f = self._get_ranges_hinted(relpath, coalesced)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/transport/http/__init__.py", line 232, in _get_ranges_hinted
    code, f = self._get(relpath, ranges)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/transport/http/_urllib.py", line 139, in _get
    data = handle_response(abspath, code, response.headers, response)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/transport/http/response.py", line 264, in handle_response
    return HttpMultipartRangeResponse(url, content_type, data)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/transport/http/response.py", line 198, in __init__
    RangeFile.__init__(self, path, input_file)
  File "/home/mwh/src/bzr/bzr.dev/bzrlib/transport/http/response.py", line 76, in __init__
    self._data = input_file.read()
  File "socket.py", line 291, in read
    data = self._sock.recv(recv_size)
  File "httplib.py", line 529, in read
    s = self.fp.read(amt)
  File "socket.py", line 309, in read
    data = self._sock.recv(recv_size)
error: (4, 'Interrupted system call')

Related branches

Vincent Ladeuil (vila)
Changed in bzr:
assignee: nobody → v-ladeuil
Revision history for this message
John A Meinel (jameinel) wrote : Re: SIGQUIT debugging breaks networking

It also drops SSH connections.

Changed in bzr:
importance: Undecided → Medium
status: New → Triaged
Vincent Ladeuil (vila)
Changed in bzr:
assignee: v-ladeuil → nobody
Martin Pool (mbp)
summary: - SIGQUIT debugging breaks networking
+ SIGQUIT debugging breaks networking because httplib (and others?) don't
+ handle EINTR properly
Revision history for this message
Andrew Bennetts (spiv) wrote :

I expect to fix this via using signal.siginterrupt, as described in bug 496813.

Changed in bzr:
assignee: nobody → Andrew Bennetts (spiv)
status: Triaged → In Progress
Revision history for this message
Andrew Bennetts (spiv) wrote :

I'm not actively working on this anymore. There's a fundamental trade-off between risking EINTR vs. being able to interrupt code blocked in e.g. a read call. Arguably the status quo is better, as at least you get a pdb prompt pretty reliably, whereas if we use siginterrupt then a process stuck in a read call that never returns will never act on a SIGQUIT signal. As an added complication signal.siginterrupt was actually mostly broken until Python 2.6.3 or thereabouts.

It would be nice to do something about this, but I'm not sure what, and I'm not likely to spend time thinking about this for the foreseeable future.

Changed in bzr:
importance: Medium → Wishlist
status: In Progress → Confirmed
Andrew Bennetts (spiv)
Changed in bzr:
assignee: Andrew Bennetts (spiv) → nobody
Jelmer Vernooij (jelmer)
tags: added: check-for-breezy
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.