1.1 --- a/core/systems/HandleSys.cpp Mon Oct 22 07:54:04 2007 +0000
1.2 +++ b/core/systems/HandleSys.cpp Mon Oct 22 08:53:15 2007 +0000
1.3 @@ -33,6 +33,7 @@
1.4 #include "ShareSys.h"
1.5 #include "PluginSys.h"
1.6 #include "ExtensionSys.h"
1.7 +#include "Logger.h"
1.8 #include <assert.h>
1.9 #include <string.h>
1.10
1.11 @@ -260,6 +261,24 @@
1.12 return true;
1.13 }
1.14
1.15 +HandleError HandleSystem::TryAllocHandle(unsigned int *handle)
1.16 +{
1.17 + if (m_FreeHandles == 0)
1.18 + {
1.19 + if (m_HandleTail >= HANDLESYS_MAX_HANDLES)
1.20 + {
1.21 + return HandleError_Limit;;
1.22 + }
1.23 + *handle = ++m_HandleTail;
1.24 + }
1.25 + else
1.26 + {
1.27 + *handle = m_Handles[m_FreeHandles--].freeID;
1.28 + }
1.29 +
1.30 + return HandleError_None;
1.31 +}
1.32 +
1.33 HandleError HandleSystem::MakePrimHandle(HandleType_t type,
1.34 QHandle **in_pHandle,
1.35 unsigned int *in_index,
1.36 @@ -267,7 +286,9 @@
1.37 IdentityToken_t *owner,
1.38 bool identity)
1.39 {
1.40 + HandleError err;
1.41 unsigned int owner_index = 0;
1.42 + bool retried_alloc = false;
1.43
1.44 if (owner && (IdentityHandle(owner, &owner_index) != HandleError_None))
1.45 {
1.46 @@ -275,15 +296,13 @@
1.47 }
1.48
1.49 unsigned int handle;
1.50 - if (m_FreeHandles == 0)
1.51 + if ((err = TryAllocHandle(&handle)) != HandleError_None)
1.52 {
1.53 - if (m_HandleTail >= HANDLESYS_MAX_HANDLES)
1.54 + if (!TryAndFreeSomeHandles()
1.55 + || (err = TryAllocHandle(&handle)) != HandleError_None)
1.56 {
1.57 - return HandleError_Limit;;
1.58 + return err;
1.59 }
1.60 - handle = ++m_HandleTail;
1.61 - } else {
1.62 - handle = m_Handles[m_FreeHandles--].freeID;
1.63 }
1.64
1.65 QHandle *pHandle = &m_Handles[handle];
1.66 @@ -329,7 +348,9 @@
1.67 pIdentity->ch_prev = handle;
1.68 pIdentity->ch_next = handle;
1.69 pHandle->ch_prev = 0;
1.70 - } else {
1.71 + }
1.72 + else
1.73 + {
1.74 /* Link previous node to us (forward) */
1.75 m_Handles[pIdentity->ch_next].ch_next = handle;
1.76 /* Link us to previous node (backwards) */
1.77 @@ -338,7 +359,9 @@
1.78 pIdentity->ch_next = handle;
1.79 }
1.80 pIdentity->refcount++;
1.81 - } else {
1.82 + }
1.83 + else
1.84 + {
1.85 pHandle->ch_prev = 0;
1.86 }
1.87
1.88 @@ -918,11 +941,65 @@
1.89 return true;
1.90 }
1.91
1.92 +bool HandleSystem::TryAndFreeSomeHandles()
1.93 +{
1.94 + IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
1.95 + IPlugin *highest_owner = NULL;
1.96 + unsigned int highest_handle_count = 0;
1.97 +
1.98 + /* Search all plugins */
1.99 + while (pl_iter->MorePlugins())
1.100 + {
1.101 + IPlugin *plugin = pl_iter->GetPlugin();
1.102 + IdentityToken_t *identity = plugin->GetIdentity();
1.103 + unsigned int handle_count = 0;
1.104 +
1.105 + if (identity == NULL)
1.106 + {
1.107 + continue;
1.108 + }
1.109 +
1.110 + /* Search all handles */
1.111 + for (unsigned int i = 1; i <= m_HandleTail; i++)
1.112 + {
1.113 + if (m_Handles[i].set != HandleSet_Used)
1.114 + {
1.115 + continue;
1.116 + }
1.117 + if (m_Handles[i].owner == identity)
1.118 + {
1.119 + handle_count++;
1.120 + }
1.121 + }
1.122 +
1.123 + if (handle_count > highest_handle_count)
1.124 + {
1.125 + highest_owner = plugin;
1.126 + highest_handle_count = handle_count;
1.127 + }
1.128 +
1.129 + pl_iter->NextPlugin();
1.130 + }
1.131 +
1.132 + if (highest_owner == NULL || highest_handle_count == 0)
1.133 + {
1.134 + return false;
1.135 + }
1.136 +
1.137 + g_Logger.LogFatal("[SM] MEMORY LEAK DETECTED IN PLUGIN (file \"%s\")", highest_owner->GetFilename());
1.138 + g_Logger.LogFatal("[SM] Reloading plugin to free %d handles.", highest_handle_count);
1.139 + g_Logger.LogFatal("[SM] Contact the author(s) of this plugin to correct this error.", highest_handle_count);
1.140 +
1.141 + highest_owner->GetContext()->n_err = SP_ERROR_MEMACCESS;
1.142 +
1.143 + return g_PluginSys.UnloadPlugin(highest_owner);
1.144 +}
1.145 +
1.146 void HandleSystem::Dump(FILE *fp)
1.147 {
1.148 fprintf(fp, "%-10.10s\t%-20.20s\t%-20.20s\n", "Handle", "Owner", "Type");
1.149 fprintf(fp, "---------------------------------------------\n");
1.150 - for (unsigned int i=1; i<=m_HandleTail; i++)
1.151 + for (unsigned int i = 1; i <= m_HandleTail; i++)
1.152 {
1.153 if (m_Handles[i].set != HandleSet_Used)
1.154 {
1.155 @@ -938,14 +1015,20 @@
1.156 if (pOwner == g_pCoreIdent)
1.157 {
1.158 owner = "CORE";
1.159 - } else if (pOwner == g_PluginSys.GetIdentity()) {
1.160 + }
1.161 + else if (pOwner == g_PluginSys.GetIdentity())
1.162 + {
1.163 owner = "PLUGINSYS";
1.164 - } else {
1.165 + }
1.166 + else
1.167 + {
1.168 CExtension *ext = g_Extensions.GetExtensionFromIdent(pOwner);
1.169 if (ext)
1.170 {
1.171 owner = ext->GetFilename();
1.172 - } else {
1.173 + }
1.174 + else
1.175 + {
1.176 CPlugin *pPlugin = g_PluginSys.GetPluginFromIdentity(pOwner);
1.177 if (pPlugin)
1.178 {
1.179 @@ -953,7 +1036,9 @@
1.180 }
1.181 }
1.182 }
1.183 - } else {
1.184 + }
1.185 + else
1.186 + {
1.187 owner = "NONE";
1.188 }
1.189 const char *type = "ANON";