Document threading limitations and show multiprocessing example.
This commit is contained in:
+9
-6
@@ -28,6 +28,7 @@ def uniqueID():
|
||||
_seq_lock.release()
|
||||
return seqno
|
||||
|
||||
## @private
|
||||
OPTIONAL_CALLBACKS = {
|
||||
'connect':(P_NR_CONN,P_NOCONNECT),
|
||||
'hello':(P_NR_HELO,P_NOHELO),
|
||||
@@ -40,6 +41,7 @@ OPTIONAL_CALLBACKS = {
|
||||
'header':(P_NR_HDR,P_NOHDRS)
|
||||
}
|
||||
|
||||
## @private
|
||||
def decode_mask(bits,names):
|
||||
t = [ (s,getattr(milter,s)) for s in names]
|
||||
nms = [s for s,m in t if bits & m]
|
||||
@@ -47,6 +49,13 @@ def decode_mask(bits,names):
|
||||
if bits: nms += hex(bits)
|
||||
return nms
|
||||
|
||||
## @fn set_flags(flags)
|
||||
# @brief Enable optional %milter actions.
|
||||
# Certain %milter actions need to be enabled before calling milter.runmilter()
|
||||
# or they throw an exception.
|
||||
# @param flags Bit ored mask of optional actions to enable
|
||||
|
||||
|
||||
## Class decorator to enable optional protocol steps.
|
||||
# P_SKIP is enabled by default when supported, but
|
||||
# applications may wish to enable P_HDR_LEADSPC
|
||||
@@ -538,12 +547,6 @@ class Milter(Base):
|
||||
# change in configuration.
|
||||
factory = Milter
|
||||
|
||||
## @fn set_flags(flags)
|
||||
# @brief Enable optional %milter actions.
|
||||
# Certain %milter actions need to be enabled before calling milter.runmilter()
|
||||
# or they throw an exception.
|
||||
# @param flags Bit ored mask of optional actions to enable
|
||||
|
||||
## @private
|
||||
# @brief Connect context to connection instance and return enabled callbacks.
|
||||
def negotiate_callback(ctx,opts):
|
||||
|
||||
@@ -69,8 +69,7 @@ Not-so-quick Installation
|
||||
First install Sendmail. Make sure you read libmilter/README in the Sendmail
|
||||
source directory, and make sure you enable libmilter before you build. The
|
||||
8.11 series had libmilter marked as FFR (For Future Release); 8.12
|
||||
officially
|
||||
supports libmilter, but it's still not built by default.
|
||||
officially supports libmilter, but it's still not built by default.
|
||||
|
||||
Install Python, and enable threading in Modules/Setup.
|
||||
|
||||
|
||||
+18
-1
@@ -1,6 +1,5 @@
|
||||
## @mainpage Writing Milters in Python
|
||||
#
|
||||
#
|
||||
# At the lowest level, the <code>milter</code> module provides a thin wrapper
|
||||
# around the <a href="https://www.milter.org/developers/api/index"> sendmail
|
||||
# libmilter API</a>. This API lets you register callbacks for a number of
|
||||
@@ -34,3 +33,21 @@
|
||||
# The <code>mime</code> module provides a wrapper for the Python email package
|
||||
# that fixes some bugs, and simplifies modifying selected parts of a MIME
|
||||
# message.
|
||||
#
|
||||
# @section threading
|
||||
#
|
||||
# The libmilter library which pymilter wraps
|
||||
# <a href="https://www.milter.org/developers/overview#SignalHandling">handles
|
||||
# all signals</a> itself, and expects to be called from a single main thread.
|
||||
# It handles SIGTERM, SIGHUP, and SIGINT, mapping the first two to
|
||||
# <a href="https://www.milter.org/developers/api/smfi_stop">smfi_stop</a>
|
||||
# and the last to an internal ABORT.
|
||||
#
|
||||
# If you use python threads or threading modules, then signal handling gets
|
||||
# confused. Threads may still be useful, but you may need to provide an
|
||||
# alternate means of causing graceful shutdown.
|
||||
#
|
||||
# You may find the
|
||||
# <a href="http://docs.python.org/release/2.6.6/library/multiprocessing.html">
|
||||
# multiprocessing</a> module useful. It can be a drop-in
|
||||
# replacement for threading as illustrated in @ref milter-template.py.
|
||||
|
||||
+20
-4
@@ -14,7 +14,13 @@ import email
|
||||
import sys
|
||||
from socket import AF_INET, AF_INET6
|
||||
from Milter.utils import parse_addr
|
||||
if True:
|
||||
from multiprocessing import Process as Thread, Queue
|
||||
else:
|
||||
from threading import Thread
|
||||
from Queue import Queue
|
||||
|
||||
logq = Queue(maxsize=4)
|
||||
|
||||
class myMilter(Milter.Base):
|
||||
|
||||
@@ -117,16 +123,24 @@ class myMilter(Milter.Base):
|
||||
## === Support Functions ===
|
||||
|
||||
def log(self,*msg):
|
||||
print "%s [%d]" % (time.strftime('%Y%b%d %H:%M:%S'),self.id),
|
||||
logq.put((msg,self.id,time.time()))
|
||||
|
||||
def background():
|
||||
while True:
|
||||
t = logq.get()
|
||||
if not t: break
|
||||
msg,id,ts = t
|
||||
print "%s [%d]" % (time.strftime('%Y%b%d %H:%M:%S',time.localtime(ts)),id),
|
||||
# 2005Oct13 02:34:11 [1] msg1 msg2 msg3 ...
|
||||
for i in msg: print i,
|
||||
print
|
||||
|
||||
|
||||
## ===
|
||||
|
||||
def main():
|
||||
socketname = "/tmp/pythonsock"
|
||||
bt = Thread(target=background)
|
||||
bt.start()
|
||||
socketname = "/home/stuart/pythonsock"
|
||||
timeout = 600
|
||||
# Register to have the Milter factory create instances of your class:
|
||||
Milter.factory = myMilter
|
||||
@@ -136,7 +150,9 @@ def main():
|
||||
Milter.set_flags(flags) # tell Sendmail which features we use
|
||||
print "%s milter startup" % time.strftime('%Y%b%d %H:%M:%S')
|
||||
sys.stdout.flush()
|
||||
Milter.runmilter("test",socketname,timeout)
|
||||
Milter.runmilter("pythonfilter",socketname,timeout)
|
||||
logq.put(None)
|
||||
bt.join()
|
||||
print "%s bms milter shutdown" % time.strftime('%Y%b%d %H:%M:%S')
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+4
-2
@@ -13,8 +13,9 @@ License: GPLv2+
|
||||
Group: Development/Libraries
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
||||
Url: http://www.bmsi.com/python/milter.html
|
||||
Requires: %{pythonbase}, sendmail >= 8.13
|
||||
# Need python2.4 specific pydns, not the version for system python
|
||||
# python-2.6.4 gets RuntimeError: not holding the import lock
|
||||
Requires: %{pythonbase} >= 2.6.5, sendmail >= 8.13
|
||||
# Need python2.6 specific pydns, not the version for system python
|
||||
Requires: %{pythonbase}-pydns
|
||||
# Needed for callbacks, not a core function but highly useful for milters
|
||||
BuildRequires: ed, %{pythonbase}-devel, sendmail-devel >= 8.13
|
||||
@@ -77,6 +78,7 @@ rm -rf $RPM_BUILD_ROOT
|
||||
* Wed Mar 02 2010 Stuart Gathman <stuart@bmsi.com> 0.9.5-1
|
||||
- Print milter.error for invalid callback return type.
|
||||
(Since stacktrace is empty, the TypeError exception is confusing.)
|
||||
- Fix milter-template.py
|
||||
|
||||
* Wed Mar 02 2010 Stuart Gathman <stuart@bmsi.com> 0.9.4-1
|
||||
- Handle IP6 in Milter.utils.iniplist()
|
||||
|
||||
Reference in New Issue
Block a user