English 中文(简体)
Avoid OpenERP audittrail bug
原标题:

I d like to manage OpenERP user s activity by installing the audittrail module.
After creating some rules ( define which user, which object and which activity (create, update..) will be monitored). I update a product to see it works.
When I ve tried to update a product i got the system error. Seeing the log, I get
[2010-08-31 12:53:35,042] Cursor not closed explicitly
[2010-08-31 12:53:35,043] Cursor was created at /home/pilgrim/working/sources/addons/audittrail/audittrail.py:204

Here the line that causes error
cr = pooler.get_db(db).cursor()
Looking at sql_db.py, I get the comment

def __del__(self):
    if not self.__closed:
        # Oops.  self  has not been closed explicitly.
        # The cursor will be deleted by the garbage collector,
        # but the database connection is not put back into the connection
        # pool, preventing some operation on the database like dropping it.
        # This can also lead to a server overload.
        msg = "Cursor not closed explicitly
"  
              "Cursor was created at %s:%s" % self.__caller
        log(msg, netsvc.LOG_WARNING)
        self.close()

Since I m new to Python, I don t know how to overcome this issue?
Any hint to get over this?
Thank

问题回答

t would be important to see the source code to understand whats going on. But from what you have posted it looks like the previous cursor was not closed explicitly.

cr = sqldb.db_connect(dbname).cursor()
.........
cr.close()
cr = None

I would suggest that you hack audittrail.py to find where ever you are creating the cursor and where ever you close them. A typical issue arises in incorrect handling of exceptions, causing code to jump over normal closure.

Try placing a try, except and finally clause around the questionable cursor operation. That should help you to get around the problem.

I think I find the answer. See an example

def a():  
  try:
    print  before return  
    return 1
  finally:
    print  in finally 

call a()

before return 
in finally
1

It s normal. OK. Try another example ( code extract from audittrail.py)

def do_something_with_db(db):
   // open cusror again
   cr = db.cursor()
   // do somethign
   // close cursor internally
   cr.close()
def execute(db)
   // 1, open connection and open cursor
   cr = db.cursor
   try:
        //2, do something with db, seeing that this method will open cursor again
       return do_something_with_db(db)
   finally:
       cr.close()

Seeing that the implementation of do_something_with_db trying to open the cursor ( can be called connection) but the current one is not explicitly closed. So the solution is simple: Pass the current cr around

Before
**do_something_with_db(db)**
after
**do_something_with_db(cr)**

Now the error s gone.

@Don Kirkby: Yes, we should experiment with try...finally

Can you run OpenERP in a debugger like the PyDev plug in for Eclipse? I find that the most effective way to track down problems. I haven t used the audit trail module, but I took a quick look at the source code, and it appears that the cursor is being opened near the beginning of log_fct(). (I would have expected it to report line 207, which version are you running?) Here s what I think is the relevant code:

def log_fct(self, db, uid, passwd, object, method, fct_src, *args):
    logged_uids = []
    pool = pooler.get_pool(db)
    cr = pooler.get_db(db).cursor() # line 207 in version 5.0.12

    # ...

    if method in ( create ):

        # ...

        cr.close()
        return res_id

    # ...

    cr.close()

It looks like there are several return statements in the method, but each one seems to call cr.close() first, so I don t see any obvious problems. Try running it in the debugger with a break point in this method. If that s not possible, you can try writing to the log with something like this:

    logger = netsvc.Logger()
    logger.notifyChannel( audittrail , netsvc.LOG_INFO,  something happened )

Update: You commented that this happens under heavy load. Perhaps an exception is being thrown and the cursor is not being closed. You could use a try ... finally statement to make sure that the cursor is always closed. Here s how the sample above would look after converting it:

def log_fct(self, db, uid, passwd, object, method, fct_src, *args):
    logged_uids = []
    pool = pooler.get_pool(db)
    cr = pooler.get_db(db).cursor() # line 207 in version 5.0.12
    try:

        # ...

        if method in ( create ):

            # ...

            return res_id

        # ...

    finally:
        cr.close()




相关问题
Can Django models use MySQL functions?

Is there a way to force Django models to pass a field to a MySQL function every time the model data is read or loaded? To clarify what I mean in SQL, I want the Django model to produce something like ...

An enterprise scheduler for python (like quartz)

I am looking for an enterprise tasks scheduler for python, like quartz is for Java. Requirements: Persistent: if the process restarts or the machine restarts, then all the jobs must stay there and ...

How to remove unique, then duplicate dictionaries in a list?

Given the following list that contains some duplicate and some unique dictionaries, what is the best method to remove unique dictionaries first, then reduce the duplicate dictionaries to single ...

What is suggested seed value to use with random.seed()?

Simple enough question: I m using python random module to generate random integers. I want to know what is the suggested value to use with the random.seed() function? Currently I am letting this ...

How can I make the PyDev editor selectively ignore errors?

I m using PyDev under Eclipse to write some Jython code. I ve got numerous instances where I need to do something like this: import com.work.project.component.client.Interface.ISubInterface as ...

How do I profile `paster serve` s startup time?

Python s paster serve app.ini is taking longer than I would like to be ready for the first request. I know how to profile requests with middleware, but how do I profile the initialization time? I ...

Pragmatically adding give-aways/freebies to an online store

Our business currently has an online store and recently we ve been offering free specials to our customers. Right now, we simply display the special and give the buyer a notice stating we will add the ...

Converting Dictionary to List? [duplicate]

I m trying to convert a Python dictionary into a Python list, in order to perform some calculations. #My dictionary dict = {} dict[ Capital ]="London" dict[ Food ]="Fish&Chips" dict[ 2012 ]="...

热门标签