[Python-bugs-list] Re: socket left in FIN_WAIT_2 state (PR#108)

clarence@netlojix.com clarence@netlojix.com
Tue, 19 Oct 1999 13:52:19 -0400 (EDT)


> My guess is that you are being fooled by reference counts and the "_"
> variable with this example.  If you typed x at the >>> prompt just
> before you did "del x", the _ builtin variable holds a reference to
You are exactly right, I did that.  Sorry.

> 
> The question now remains, why do you observe this behavior in
> SocketServer?  I still want to see the code you are actually using --
> maybe there's a clue there.  If not, I'll have to close this PR as
> irreproducible...
Here is the server code.  Your comment about reference counts made me
want to mention that I am using StreamRequestHandler, which does a 
makefile() on the socket, but if I read the code correctly, that doesn't
actually share the socket object?  (Seems to just dup() the fd and make
a wholly distinct object.)  I'm hoping I haven't set you on a wild goose
chase....

#!/usr/local/bin/python

import sys
import os
import string
import SocketServer
import urllib
import time

sys.path.insert(0, '/home/netaid/lib')
import NetAid

import MySQL
db = MySQL.connect('', NetAid.DBAuth[0], NetAid.DBAuth[1])
db.selectdb(NetAid.DBName)
import DonateTable
DonateTable = DonateTable.DonateTable()
import CommentsTable
CommentsTable = CommentsTable.CommentsTable()

class DBQueryHandler(SocketServer.StreamRequestHandler):
	def handle(self):
		try:
			self.ReadRequest()
			self.DoQuery()
			self.SendResults()
		except:
			pass
	def ReadRequest(self):
		readline = self.rfile.readline
		strip = string.strip
		Op = strip(readline())
		if Op == 'GET':
			self.ccnum = strip(readline())
			self.ccname = strip(readline())
			self.amount = int(strip(readline()))
			self.DoQuery = self.Fetch
			self.SendResults = self.SendRecords
		elif Op == 'REFUND':
			self.id = strip(readline())
			self.ccnum = strip(readline())
			self.DoQuery = self.DoRefund
			self.SendResults = self.OK
		elif Op == 'COMMENT':
			self.id = strip(readline())
			self.comment = urllib.unquote(strip(readline()))
			self.DoQuery = self.AddComment
			self.SendResults = self.OK
			pass
	def Fetch(self):
		where = ''' where cardnumber='%s' and cardname='%s'
				and amount=%d
			''' % (self.ccnum, self.ccname, self.amount)
		self.recs = DonateTable.ReadAll(db, where)
		for rec in self.recs:
			comments = CommentsTable.ReadAll(db,
				"where donation_id=%d order by timestamp" % rec['id'])
			c = ''
			for comment in comments:
				c = c + ';' + comment['comment']
			rec['comments'] = c
	def SendRecords(self):
		write = self.wfile.write
		write('%d\n' % len(self.recs))
		for rec in self.recs:
			write('5\n')
			write('id:%s\n' % rec['id'])
			write('status:%s\n'% rec['status'])
			write('cc:%s\n' % rec['cardnumber'][:8])
			write('date:%s\n' % rec['donation_date'])
			write('comment:%s\n' % rec['comments'])
	def DoRefund(self):
		rec = DonateTable.ReadOne(db, {'id':self.id})
		if not rec:
			self.message = '0Invalid record identifier'
			return
		if rec['cardnumber'][:8] <> self.ccnum:
			self.message = '0Record mismatch'
			return
		if rec['status'] in 'rR':
			self.message = '0Refund already requested'
			return
		if rec['status'] in 'F':
			self.message = '0Cannot refund -- charge failed'
			return
		if rec['status'] in 'NC':
			self.message = '0Cannot refund -- charge in progress'
			return
		DonateTable.Update(db, {'id':self.id}, {'status':'r'})
		self.message = '1Ok, refund requested'
	def OK(self):
		self.wfile.write('%s\n' % self.message)
	def AddComment(self):
		New = {'timestamp':int(time.time()), 'donation_id':self.id,
			'comment':self.comment}
		CommentsTable.Add(New, db)
		self.message = '1Ok'

Server = SocketServer.TCPServer(('', NetAid.DBQueryPort), DBQueryHandler)
Server.serve_forever()