3442: Cycle in Depends On causes Review Request Drafts to lock out of publishing

thom.******@gmai***** (Google Code) (Is this you? Claim this profile.)
July 11, 2014
What version are you running?

What's the URL of the page containing the problem?

/api/review-requests/#####/draft/  [accessed through /r/#####/ ] 

What steps will reproduce the problem?
1. Create a review (#1). Publish it.
2. Create a review (#2). Publish it.
3. Update Review #2 to Depend On #1. Publish.
4. Update Review #1 to Depend On #2. 

What is the expected output? 

Expected is a few possible situations: The reviews are publishable; or you get a validation error when you attempt to introduce a cycle in the Depends On Graph.  I imagine users would prefer the first:  There are situations where code changes in multiple repositories must be committed at the same time thus they're interdependant.

What do you see instead?

The Review Request Draft gives a 500 error after some time due to a Runtime error: maximum recursion depth.

Work around is to create new review requests but if either of the reviews has history, they're both totally locked up. The user can't even discard their draft either after adding the depends on cycle.

What operating system are you using? What browser?

Server is Debian; triggered exception from modern Firefox and Chrome.

Please provide any additional information below.

RuntimeError: maximum recursion depth exceeded

Partial Traceback: (Sentry removes some of the frames)

  File "django/core/handlers/base.py", line 199, in get_response
    response = middleware_method(request, response)
  File "django/middleware/http.py", line 14, in process_response
    response['Content-Length'] = str(len(response.content))
  File "djblets/webapi/core.py", line 291, in _get_content
  File "djblets/webapi/core.py", line 92, in encode
    return super(JSONEncoderAdapter, self).encode(o)
  File "json/encoder.py", line 367, in encode
    chunks = list(self.iterencode(o))
  File "json/encoder.py", line 309, in _iterencode
    for chunk in self._iterencode_dict(o, markers):
  File "json/encoder.py", line 275, in _iterencode_dict
    for chunk in self._iterencode(value, markers):
  File "json/encoder.py", line 309, in _iterencode
    for chunk in self._iterencode_dict(o, markers):
  File "json/encoder.py", line 275, in _iterencode_dict
    for chunk in self._iterencode(value, markers):
  File "json/encoder.py", line 306, in _iterencode
    for chunk in self._iterencode_list(o, markers):
  File "json/encoder.py", line 204, in _iterencode_list
    for chunk in self._iterencode(value, markers):
  File "json/encoder.py", line 317, in _iterencode
    for chunk in self._iterencode_default(o, markers):
  File "django/db/models/query.py", line 304, in get
    num = len(clone)
  File "django/db/models/query.py", line 77, in __len__
  File "django/db/models/query.py", line 857, in _fetch_all
    self._result_cache = list(self.iterator())
  File "django/db/models/query.py", line 230, in iterator
    obj = model(*row_data)
  File "django/db/models/base.py", line 419, in __init__
    signals.post_init.send(sender=self.__class__, instance=self)
  File "django/dispatch/dispatcher.py", line 185, in send
    response = receiver(signal=self, sender=sender, **named)
  File "djblets/db/fields.py", line 206, in post_init
    value = self.loads(value)
  File "djblets/db/fields.py", line 229, in loads
    val = json.loads(val, encoding=settings.DEFAULT_CHARSET)
  File "json/__init__.py", line 318, in loads
    return cls(encoding=encoding, **kw).decode(s)
  File "json/decoder.py", line 319, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "json/decoder.py", line 336, in raw_decode
    obj, end = self._scanner.iterscan(s, **kw).next()
  File "json/scanner.py", line 55, in iterscan
    rval, next_pos = action(m, context)
#1 david
  • +PendingReview
  • +Project-Djblets
  • +david
#2 david
Fixed in djblets release-0.8.x (85eb686). Thanks!
  • -PendingReview