I think Lynne was hinting at this before, but anyway - the cleanup2 scheduled task removes any entries from the attachment table that are older than 1 hour and have contentid = 0. So the fact that you saw the record had contentid=0 seems to be the problem. In includes/class_dm_threadpost.php around line 526 is this code:
PHP Code:
if ($this->info['posthash'] AND $this->fetch_field('attach') AND $postid)
{
$this->dbobject->query_write("
UPDATE " . TABLE_PREFIX . "attachment
SET
contentid = $postid,
posthash = ''
WHERE
posthash = '" . $this->dbobject->escape_string($this->info['posthash']) . "'
AND
userid = " . intval($this->fetch_field('userid', 'post')) . "
");
}
That's suppose to be executed at the same time that the post is posted, to set the content id to the postid and to erase the posthash. It might be interesting to know if that's getting executed (when someone posts with an attachment), and if not, why not (which part of the condition is false). Since you have full access to your server you could do something like put in some code to open a debug file and write out some info (which is how I do a lot of debugging).