Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


LUA Threads and Mutexes

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting
View previous topic :: View next topic  
Author Message
tomerminator
Newbie cheater
Reputation: 0

Joined: 20 Nov 2024
Posts: 10

PostPosted: Sat Dec 14, 2024 3:02 am    Post subject: LUA Threads and Mutexes Reply with quote

I'm writing a multithreaded script in LUA.
I have some shared variables to which I must manage the access.
After reading a bit online, I found that LUA does not have mutexes, so I wanted to know how you handle these kind of problems?

Thanks in advanece.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25765
Location: The netherlands

PostPosted: Sat Dec 14, 2024 3:41 am    Post subject: Reply with quote

most of lua in CE is thread safe, as in a var/table can only be accessed by one thread at a time

but in case you want to deal with it, look up celua.txt and look for CriticalSection, Event, Semaphore and
MultiReadExclusiveWriteSynchronizer

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
tomerminator
Newbie cheater
Reputation: 0

Joined: 20 Nov 2024
Posts: 10

PostPosted: Sat Dec 14, 2024 5:48 am    Post subject: Reply with quote

Dark Byte wrote:
most of lua in CE is thread safe, as in a var/table can only be accessed by one thread at a time

but in case you want to deal with it, look up celua.txt and look for CriticalSection, Event, Semaphore and
MultiReadExclusiveWriteSynchronizer


Thank you for the quick reply Dark Byte!
I'm missing how can CE handle all the other threads \ tables I create in my own scripts and making them "thread safe".
I'll look into what you suggested, "MultiReadExclusiveWriteSynchronizer" is just what I need. Thanks again!

EDIT** - celua.txt is a gold mine
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25765
Location: The netherlands

PostPosted: Sun Dec 15, 2024 11:16 am    Post subject: Reply with quote

The main thing you should watch is GUI access from other threads. That will eventually lead to heap corruption and random memory location writes

you can prevent that using synchronize e.g:
Code:

...your thread code...
local somethreadvar='some data'
...
synchronize(function()   --runs in the main thread
  labelOutput.Caption='Data is '..somethreadvar
end)
...continue your thread code...

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
tomerminator
Newbie cheater
Reputation: 0

Joined: 20 Nov 2024
Posts: 10

PostPosted: Mon Dec 30, 2024 2:26 am    Post subject: Reply with quote

Dark Byte wrote:
The main thing you should watch is GUI access from other threads. That will eventually lead to heap corruption and random memory location writes

you can prevent that using synchronize e.g:
Code:

...your thread code...
local somethreadvar='some data'
...
synchronize(function()   --runs in the main thread
  labelOutput.Caption='Data is '..somethreadvar
end)
...continue your thread code...


Thank you! That fixed some weird exceptions I had.
Where should I look at if I’m not getting any exceptions but the main gui thread is frozen?
My program is using the ‘synchronized’ keyword whenever a gui-related action is executed.
If I create a criticalSection for syncing my lua threads, should enter and leave also be done in a synchronized fashion? If one of the threads crashes inside a synchronized segment, would it cause CE to stop responding?

*edit- I think that my questions is basically how is synchronize implemented, does the caller thread halt until the main thread finishes the execution? What happens if there there is a synchronized call inside a synchronized call?
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25765
Location: The netherlands

PostPosted: Mon Dec 30, 2024 3:20 am    Post subject: Reply with quote

If a crash happens inside the synchronized area it will likely crash yes, but if it's normal GUI access it really shouldn't (and if it would let's just say the rest of CE will soon follow anyhow)

synchronize will stop executing and wait for the main GUI thread to execute the code inside synchronize
when done the thread resumes

synchronize within the main thread just instantly calls the code.

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
tomerminator
Newbie cheater
Reputation: 0

Joined: 20 Nov 2024
Posts: 10

PostPosted: Mon Dec 30, 2024 3:36 am    Post subject: Reply with quote

Dark Byte wrote:
If a crash happens inside the synchronized area it will likely crash yes, but if it's normal GUI access it really shouldn't (and if it would let's just say the rest of CE will soon follow anyhow)

synchronize will stop executing and wait for the main GUI thread to execute the code inside synchronize
when done the thread resumes

synchronize within the main thread just instantly calls the code.


I see! I’ll look elsewhere. Thanks again.
Last thing that pops in mind -
Can synchronized be used as a mutex of sorts to access a shared (global) variable?
If multiple threads try to run a synchronized part simultaneously, would there be concurrency or would one thread halt after another (w/e the order)? (To summarize, are there a couple of “gui” threads, or a single one executing the sync parts?)


Edit: Nvm, I read your reply again and I assume there is just one.
Thank you for your time.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25765
Location: The netherlands

PostPosted: Mon Dec 30, 2024 7:28 am    Post subject: Reply with quote

Correct, there's just one main GUI thread, and it will execute the synchronize calls it receives in sequence. (and as mentioned, synchronize in the main GUI thread will just execute the code immediately)


Quote:

Where should I look at if I’m not getting any exceptions but the main gui thread is frozen?

I missed this in the reply. When this happens the main thread is running inside an infinite loop or very long code and it's not calling checkSynchronize nor processMessages

In general, do NOT use infinite loops when the code runs inside the main thread. Same goes for long running codesnippets. (eventually windows will mark the application as non-responsive and bad thing happen at that point)

if you want the user to not do anything while the program is processing things, use a form displayed using showModal(), and set the form's OnCloseQuery to return false. Only allow your code to close the form when it is done
(again, run the code on a separate thread, and only synchronize when closing the form)

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4691

PostPosted: Mon Dec 30, 2024 2:04 pm    Post subject: Reply with quote

tomerminator wrote:
Can synchronized be used as a mutex of sorts to access a shared (global) variable?
If you're talking about Lua globals, that's probably unnecessary. CE made Lua thread-safe by basically putting one big mutex over everything so only one thread can execute Lua at any given time. Regarding pure Lua, data races won't happen.
Code:
local n_iter = 10000000

local function test(n_threads)
  g = 0
  local ts = {}
  local startTime = getTickCount()
  for i = 1,n_threads do
    ts[#ts+1] = createThread(function(t)
      t.freeOnTerminate(false)
      for i=1,n_iter,1 do
        g = g + 1
      end
    end)
  end

  for _,thread in ipairs(ts) do
    thread.waitfor()
    assert(thread.Finished)
    thread.destroy()
  end

  local endTime = getTickCount()

  print('n_threads:',n_threads)
  print('g | deviation:', g, '|', g - n_iter * n_threads)
  print('time:', (endTime - startTime)/1000)
  print('time per thread:', (endTime - startTime) / 1000 / n_threads)
  print''
end

for i = 1,10 do
  test(i)
end
Notice how "time per thread" remains mostly unchanged even in environments with multiple hardware threads available. They're executed concurrently but not in parallel.

I don't know if calling a CE function releases the lock(s) that make Lua thread-safe. If it does, then calling CE functions concurrently might mean they're executed in parallel, which could lead to data races for certain operations.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
tomerminator
Newbie cheater
Reputation: 0

Joined: 20 Nov 2024
Posts: 10

PostPosted: Mon Dec 30, 2024 3:11 pm    Post subject: Reply with quote

ParkourPenguin wrote:
tomerminator wrote:
Can synchronized be used as a mutex of sorts to access a shared (global) variable?
If you're talking about Lua globals, that's probably unnecessary. CE made Lua thread-safe by basically putting one big mutex over everything so only one thread can execute Lua at any given time. Regarding pure Lua, data races won't happen.
Code:
local n_iter = 10000000

local function test(n_threads)
  g = 0
  local ts = {}
  local startTime = getTickCount()
  for i = 1,n_threads do
    ts[#ts+1] = createThread(function(t)
      t.freeOnTerminate(false)
      for i=1,n_iter,1 do
        g = g + 1
      end
    end)
  end

  for _,thread in ipairs(ts) do
    thread.waitfor()
    assert(thread.Finished)
    thread.destroy()
  end

  local endTime = getTickCount()

  print('n_threads:',n_threads)
  print('g | deviation:', g, '|', g - n_iter * n_threads)
  print('time:', (endTime - startTime)/1000)
  print('time per thread:', (endTime - startTime) / 1000 / n_threads)
  print''
end

for i = 1,10 do
  test(i)
end
Notice how "time per thread" remains mostly unchanged even in environments with multiple hardware threads available. They're executed concurrently but not in parallel.

I don't know if calling a CE function releases the lock(s) that make Lua thread-safe. If it does, then calling CE functions concurrently might mean they're executed in parallel, which could lead to data races for certain operations.

Thank you for replying! that makes some* sense.
Now im interested in knowing whether calling CE functions concurrently might break things (I'm most certainly doing that in at least 2 threads which read some part of the memory \ AOB scan).
also, should Mono\.NET functionality happen in a synchronized fashion? I.E Is it safe calling mono invoke method from a thread which is not the main thread?
Is it safe to call mono invoke method 'concurrently'?

My CE freezes seems to be random. could'nt find the cause yet. might run for 3 hours fine, and might crash after 25 minutes.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25765
Location: The netherlands

PostPosted: Mon Dec 30, 2024 3:14 pm    Post subject: This post has 1 review(s) Reply with quote

the mono library is thread safe. But long operations can lock other threads from access (fixed in the next version)
Also, there's aways the chance that mono just has a bug or unexpected situation and when that happens it's decided by mono_timeout what happens then (if it's 0, it means freeze forever)

ParkourPenguin wrote:

I don't know if calling a CE function releases the lock(s) that make Lua thread-safe. If it does, then calling CE functions concurrently might mean they're executed in parallel, which could lead to data races for certain operations.

yes, CE functions do not lock as long as they don't use Lua.
e.g putting
Code:

local r=md5memory(0x00400000,4096)

inside the for loop will show that multiple threads will improve the speed

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
tomerminator
Newbie cheater
Reputation: 0

Joined: 20 Nov 2024
Posts: 10

PostPosted: Wed Jan 01, 2025 8:18 am    Post subject: Reply with quote

Dark Byte wrote:
the mono library is thread safe. But long operations can lock other threads from access (fixed in the next version)
Also, there's aways the chance that mono just has a bug or unexpected situation and when that happens it's decided by mono_timeout what happens then (if it's 0, it means freeze forever)

ParkourPenguin wrote:

I don't know if calling a CE function releases the lock(s) that make Lua thread-safe. If it does, then calling CE functions concurrently might mean they're executed in parallel, which could lead to data races for certain operations.

yes, CE functions do not lock as long as they don't use Lua.
e.g putting
Code:

local r=md5memory(0x00400000,4096)

inside the for loop will show that multiple threads will improve the speed


mono_timeout is a parameter to where? mono_invoke_method?
I meant that CE is freezing, not the game (Or I misunderstood you.)

Is there an issue with writing my forms in Lua? would it cause any issues?

(I mean
- testFromblabla=createForm(..)
....)
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 470

Joined: 09 May 2003
Posts: 25765
Location: The netherlands

PostPosted: Wed Jan 01, 2025 8:32 am    Post subject: Reply with quote

mono_timeout is a global lua variable defined in monoscript.lua

as long as createForm and subsequent initializing and access code runs in synchronize() and doesn't enter an infinite loop inside there then it should be safe.

(next version ce version will warn for most thread issues )

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
tomerminator
Newbie cheater
Reputation: 0

Joined: 20 Nov 2024
Posts: 10

PostPosted: Fri Jan 03, 2025 7:17 am    Post subject: Reply with quote

Dark Byte wrote:
mono_timeout is a global lua variable defined in monoscript.lua

as long as createForm and subsequent initializing and access code runs in synchronize() and doesn't enter an infinite loop inside there then it should be safe.

(next version ce version will warn for most thread issues )


I was so hopeful that was the issue ;P, but it was not..

it seems like the weaker the machine is, the higher the likelyhood of the freeze to occour.
I have test my script on vm's with low amounts of cores and the freeze happens much more frequently.

Im running my script overnight basically, It uses mono, but it seems like the mono framework isnt the issue.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites