Skip to content

Commit

Permalink
parsemail: Make parsing an email atomic operation
Browse files Browse the repository at this point in the history
With the series support in production, I realized that postfix did not
serialize the spawing of parsemail.sh. I couldn't find clear
documentation about that specific case: serializing mail delivery to a
mailbox is possible, not sure when postfix is piping the mail to a
another process.

Instead of digging further and look at postfix code, implementing the
serialization in parsemail.py itself seemed like a good idea: this will
work independently to the MTA used. Not only that, but it'd also work if
we do crazy things like allowing to submit patches through another entry
point.

Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
  • Loading branch information
Damien Lespiau committed Oct 20, 2015
1 parent b423e83 commit 09a37af
Showing 1 changed file with 20 additions and 0 deletions.
20 changes: 20 additions & 0 deletions patchwork/bin/parsemail.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@
import time
import operator
import codecs
import weakref
from email import message_from_file
from email.header import Header, decode_header
from email.parser import HeaderParser
from email.utils import parsedate_tz, mktime_tz
import logging

from patchwork import lock as lockmod
from patchwork.lock import release
from patchwork.parser import parse_patch
from patchwork.models import Patch, Project, Person, Comment, State, Series, \
SeriesRevision, SeriesRevisionPatch, get_default_initial_patch_state, \
Expand Down Expand Up @@ -702,18 +705,35 @@ def setup_error_handler():

return logger

_lockref = None
def lock():
global _lockref

l = _lockref and _lockref()
if l is not None and l.held:
l.lock()
return l

l = lockmod.lock("/tmp/patchwork.parsemail.lock", timeout=30)
_lockref = weakref.ref(l)
return l

def main(args):
django.setup()
logger = setup_error_handler()
mail = message_from_file(sys.stdin)
parse_lock = None
try:
parse_lock = lock()
return parse_mail(mail)
except:
if logger:
logger.exception('Error when parsing incoming email', extra={
'mail': mail.as_string(),
})
raise
finally:
release(parse_lock)

if __name__ == '__main__':
sys.exit(main(sys.argv))

0 comments on commit 09a37af

Please sign in to comment.