Skip to content

Commit

Permalink
LuaFAR: M#3458: Падение Far в far.Timer при малых значениях периода
Browse files Browse the repository at this point in the history
  • Loading branch information
shmuz committed Oct 12, 2017
1 parent abeb30b commit 740f45b
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 41 deletions.
2 changes: 1 addition & 1 deletion plugins/luamacro/_globalinfo.lua
@@ -1,6 +1,6 @@
function export.GetGlobalInfo()
return {
Version = { 1, 0, 0, 621 },
Version = { 1, 0, 0, 622 },
MinFarVersion = { 3, 0, 0, 5063 },
Guid = win.Uuid("4EBBEFC8-2084-4B7F-94C0-692CE136894D"),
Title = "LuaMacro",
Expand Down
6 changes: 5 additions & 1 deletion plugins/luamacro/changelog
@@ -1,4 +1,8 @@
zg 08.10.2017 14:46:34 +0300 - build 621
shmuel 12.10.2017 16:44:33 +0200 - build 622

1. LuaFAR: M#3458: Падение Far в far.Timer при малых значениях периода

zg 08.10.2017 14:46:34 +0300 - build 621

1. 0003514: Возможность задать приоритет макросов, определяемым через MCTL_ADDMACRO.

Expand Down
25 changes: 14 additions & 11 deletions plugins/luamacro/luafar/exported.c
Expand Up @@ -24,6 +24,8 @@ extern int PushDNParams (lua_State *L, intptr_t Msg, intptr_t Param1, void *Para
extern int PushDMParams (lua_State *L, intptr_t Msg, intptr_t Param1);
extern intptr_t ProcessDNResult(lua_State *L, intptr_t Msg, void *Param2);
extern HANDLE Open_Luamacro(lua_State *L, const struct OpenInfo *Info);
extern HANDLE GetLuaStateTimerQueue(lua_State *L);
extern void DeleteLuaStateTimerQueue(lua_State *L);

void PackMacroValues(lua_State* L, size_t Count, const struct FarMacroValue* Values); // forward declaration

Expand Down Expand Up @@ -104,9 +106,9 @@ int pcall_msg(lua_State* L, int narg, int nret)
{
int status2 = 1;
intptr_t *Flags = &GetPluginData(L)->Flags;

*Flags |= PDF_PROCESSINGERROR;

if(GetExportFunction(L, "OnError"))
{
lua_insert(L,-2);
Expand All @@ -118,7 +120,7 @@ int pcall_msg(lua_State* L, int narg, int nret)
LF_Error(L, check_utf8_string(L, -1, NULL));
lua_pop(L, 1);
}

*Flags &= ~PDF_PROCESSINGERROR;
}

Expand Down Expand Up @@ -1223,17 +1225,18 @@ intptr_t LF_SetFindList(lua_State* L, const struct SetFindListInfo *Info)

void LF_ExitFAR(lua_State* L, const struct ExitInfo *Info)
{
HANDLE TimerQueue = NULL;
HANDLE hQueue;
(void)Info;

if(GetExportFunction(L, "ExitFAR")) //+1: Func
pcall_msg(L, 0, 0); //+0

lua_getfield(L, LUA_REGISTRYINDEX, LREG_FARTIMERQUEUE); //+1
TimerQueue = lua_touserdata(L, -1);
lua_pop(L, 1); //+0
if (TimerQueue)
DeleteTimerQueueEx(TimerQueue, NULL);
hQueue = GetLuaStateTimerQueue(L); //+0
if (hQueue)
{
DeleteLuaStateTimerQueue(L);
DeleteTimerQueueEx(hQueue, NULL);
}
}

void getPluginMenuItems(lua_State* L, struct PluginMenuItem *pmi, const char* namestrings,
Expand Down Expand Up @@ -1379,7 +1382,7 @@ intptr_t LF_ProcessDialogEvent(lua_State* L, const struct ProcessDialogEventInfo

if (*Flags & PDF_PROCESSINGERROR)
return 0;

if (Info->Event == DE_DLGPROCINIT && fde->Msg == DN_INITDIALOG)
{
*Flags &= ~PDF_DIALOGEVENTDRAWENABLE;
Expand Down Expand Up @@ -1669,7 +1672,7 @@ intptr_t LF_ProcessConsoleInput(lua_State* L, struct ProcessConsoleInputInfo *In
if(pcall_msg(L, 2, 1) == 0) //+1: Res
{
if(lua_type(L,-1) == LUA_TNUMBER && lua_tonumber(L,-1) == 0)
ret = 0;
ret = 0;
else if(lua_type(L,-1) == LUA_TTABLE)
{
FillInputRecord(L, -1, &Info->Rec);
Expand Down
76 changes: 56 additions & 20 deletions plugins/luamacro/luafar/service.c
Expand Up @@ -46,6 +46,7 @@ extern int GetExportFunction(lua_State* L, const char* FuncName);

const char FarFileFilterType[] = "FarFileFilter";
const char FarTimerType[] = "FarTimer";
const char FarTimerQueueKey[] = "FarTimerQueue";
const char FarDialogType[] = "FarDialog";
const char SettingsType[] = "FarSettings";
const char SettingsHandles[] = "FarSettingsHandles";
Expand Down Expand Up @@ -164,6 +165,21 @@ BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
return TRUE;
}

HANDLE GetLuaStateTimerQueue(lua_State *L)
{
HANDLE hQueue;
lua_getfield(L, LUA_REGISTRYINDEX, FarTimerQueueKey);
hQueue = lua_touserdata(L, -1);
lua_pop(L, 1);
return hQueue;
}

void DeleteLuaStateTimerQueue(lua_State *L)
{
lua_pushnil(L);
lua_setfield(L, LUA_REGISTRYINDEX, FarTimerQueueKey);
}

static TSynchroData* CreateSynchroData(TTimerData *td, int action, int data)
{
TSynchroData* SD = (TSynchroData*) malloc(sizeof(TSynchroData));
Expand Down Expand Up @@ -5338,13 +5354,7 @@ void CALLBACK TimerCallback(void *lpParameter, BOOLEAN TimerOrWaitFired)
TTimerData *td = (TTimerData*)lpParameter;
TSynchroData *sd;
(void)TimerOrWaitFired;
if (td->needClose)
{
DeleteTimerQueueTimer(td->hQueue, td->hTimer, NULL);
sd = CreateSynchroData(td, LUAFAR_TIMER_UNREF, 0);
td->Info->AdvControl(td->PluginGuid, ACTL_SYNCHRO, 0, sd);
}
else if (td->enabled)
if (!td->needClose && td->enabled)
{
sd = CreateSynchroData(td, LUAFAR_TIMER_CALL, 0);
td->Info->AdvControl(td->PluginGuid, ACTL_SYNCHRO, 0, sd);
Expand All @@ -5355,6 +5365,7 @@ static int far_Timer(lua_State *L)
{
TPluginData *pd;
TTimerData *td;
HANDLE hQueue;
int interval, index, tabSize;

interval = (int)luaL_checkinteger(L, 1);
Expand Down Expand Up @@ -5387,14 +5398,11 @@ static int far_Timer(lua_State *L)

lua_pushvalue(L, -2);
td->tabRef = luaL_ref(L, LUA_REGISTRYINDEX);
td->needClose = 0;
td->needClose = FALSE;
td->enabled = 1;
hQueue = GetLuaStateTimerQueue(L);

lua_getfield(L, LUA_REGISTRYINDEX, LREG_FARTIMERQUEUE);
td->hQueue = lua_touserdata(L, -1);
lua_pop(L, 1);

if (td->hQueue && CreateTimerQueueTimer(&td->hTimer,td->hQueue,TimerCallback,td,td->interval,td->interval,WT_EXECUTEDEFAULT))
if (hQueue && CreateTimerQueueTimer(&td->hTimer,hQueue,TimerCallback,td,td->interval,td->interval,WT_EXECUTEDEFAULT))
return 1;

luaL_unref(L, LUA_REGISTRYINDEX, td->tabRef);
Expand All @@ -5409,22 +5417,46 @@ TTimerData* CheckTimer(lua_State* L, int pos)
TTimerData* CheckValidTimer(lua_State* L, int pos)
{
TTimerData* td = CheckTimer(L, pos);
luaL_argcheck(L, td->needClose == 0, pos, "attempt to access closed timer");
luaL_argcheck(L, !td->needClose, pos, "attempt to access closed timer");
return td;
}

static int timer_Close(lua_State *L)
{
HANDLE hQueue;
TSynchroData* sd;
TTimerData* td = CheckTimer(L, 1);
td->needClose = 1;
if (!td->needClose)
{
td->needClose = TRUE;
hQueue = GetLuaStateTimerQueue(L);
if (hQueue)
DeleteTimerQueueTimer(hQueue, td->hTimer, NULL);
sd = CreateSynchroData(td, LUAFAR_TIMER_UNREF, 0);
td->Info->AdvControl(td->PluginGuid, ACTL_SYNCHRO, 0, sd);
}
return 0;
}

static int timer_gc(lua_State *L)
{
HANDLE hQueue;
TTimerData* td = CheckTimer(L, 1);
if (!td->needClose)
{
td->needClose = TRUE;
hQueue = GetLuaStateTimerQueue(L);
if (hQueue)
DeleteTimerQueueTimer(hQueue, td->hTimer, NULL);
}
return 0;
}

static int timer_tostring(lua_State *L)
{
TTimerData* td = CheckTimer(L, 1);

if(td->needClose == 0)
if (!td->needClose)
lua_pushfstring(L, "%s (%p)", FarTimerType, td);
else
lua_pushfstring(L, "%s (closed)", FarTimerType);
Expand Down Expand Up @@ -5469,8 +5501,12 @@ static int timer_newindex(lua_State *L)
else if(!strcmp(method, "Interval"))
{
int interval = (int)luaL_checkinteger(L, 3);
td->interval = interval < 1 ? 1 : interval;
ChangeTimerQueueTimer(td->hQueue, td->hTimer, td->interval, td->interval);
HANDLE hQueue = GetLuaStateTimerQueue(L);
if (hQueue)
{
td->interval = interval < 1 ? 1 : interval;
ChangeTimerQueueTimer(hQueue, td->hTimer, td->interval, td->interval);
}
}
else if(!strcmp(method, "OnTimer"))
{
Expand Down Expand Up @@ -5814,7 +5850,7 @@ static int far_ColorDialog(lua_State *L)

const luaL_Reg timer_methods[] =
{
{"__gc", timer_Close},
{"__gc", timer_gc},
{"__tostring", timer_tostring},
{"__index", timer_index},
{"__newindex", timer_newindex},
Expand Down Expand Up @@ -6062,7 +6098,7 @@ static int luaopen_far(lua_State *L)
if (TimerQueue)
{
lua_pushlightuserdata(L, TimerQueue);
lua_setfield(L, LUA_REGISTRYINDEX, LREG_FARTIMERQUEUE);
lua_setfield(L, LUA_REGISTRYINDEX, FarTimerQueueKey);
}

lua_newtable(L);
Expand Down
12 changes: 5 additions & 7 deletions plugins/luamacro/luafar/util.h
Expand Up @@ -24,7 +24,6 @@ _CRTIMP unsigned int __cdecl __MINGW_NOTHROW _control87 (unsigned int unNew, uns

#define LUAFAR_TIMER_CALL 0x1
#define LUAFAR_TIMER_UNREF 0x2
#define LREG_FARTIMERQUEUE "FarTimerQueue"

typedef struct
{
Expand All @@ -36,12 +35,11 @@ typedef struct
{
GUID* PluginGuid;
struct PluginStartupInfo *Info;
int interval;
int tabRef;
int needClose;
int enabled;
HANDLE hQueue;
HANDLE hTimer;
int interval; // timer period, in milliseconds
int tabRef; // reference of a Lua table in the registry
int needClose; // timer needs to be closed; boolean value
int enabled; // timer is enabled; the callback function is called only when (enabled != 0)
HANDLE hTimer; // timer handle
} TTimerData;

typedef struct
Expand Down
2 changes: 1 addition & 1 deletion plugins/luamacro/luamacro.rc
@@ -1,6 +1,6 @@
#include <farversion.hpp>

#define PLUGIN_BUILD 621
#define PLUGIN_BUILD 622
#define PLUGIN_DESC "Lua Macros for Far Manager"
#define PLUGIN_NAME "LuaMacro"
#define PLUGIN_FILENAME "luamacro.dll"
Expand Down

0 comments on commit 740f45b

Please sign in to comment.