-- Copyright 2011-16 Paul Kulchenko, ZeroBrane LLC
|
-- authors: Luxinia Dev (Eike Decker & Christoph Kubisch)
|
---------------------------------------------------------
|
|
local ide = ide
|
--[[ single instance
|
open an UDP port - if it fails it is either because
|
- IDE is running already
|
- an application is already blocking that port
|
if it fails it tries to contact the running application
|
- if it confirms being the IDE we let that instance open it, finish our application
|
- otherwise we throw an error message on the user and start like normal
|
|
probably a pitfal: an instance is running but is not visible
|
(because it was finished though the UDP thing still runs)
|
]]
|
|
if not ide.config.singleinstance then return end
|
|
local socket = require "socket"
|
local svr = socket.udp()
|
ide.singleinstanceserver = svr
|
|
local port = ide.config.singleinstanceport
|
local delay = tonumber(ide.config.singleinstance) or 1000 -- in ms
|
local success = svr:setsockname("127.0.0.1",port) -- bind on local host
|
local protocol = {client = {}, server = {}}
|
|
protocol.client.greeting = "Is this you, my master? It's me, a new instance."
|
protocol.server.greeting = "Yes it is me, running as: %s"
|
protocol.client.requestloading = "Could you please load this file for me: %s"
|
protocol.client.show = "Show yourself, my master."
|
protocol.server.answerok = "Sure. You may now leave."
|
|
if success then -- ok, server was started, we are solo
|
svr:settimeout(0) -- don't block
|
ide.timers.idle = ide:AddTimer(wx.wxGetApp(), function()
|
while true do
|
local msg, ip, port = svr:receivefrom()
|
if not msg then break end
|
|
if msg == protocol.client.greeting then
|
svr:sendto(protocol.server.greeting:format(wx.wxGetUserId()),ip,port)
|
elseif msg == protocol.client.show then
|
svr:sendto(protocol.server.answerok,ip,port)
|
ide:RequestAttention()
|
elseif msg:match(protocol.client.requestloading:gsub("%%s",".+$")) then -- ok we need to open something
|
svr:sendto(protocol.server.answerok,ip,port)
|
local filename = msg:match(protocol.client.requestloading:gsub("%%s","(.+)$"))
|
if filename then
|
ide:RequestAttention()
|
ide:ActivateFile(filename)
|
end
|
end
|
end
|
end)
|
ide.timers.idle:Start(delay,false)
|
else -- something different is running on our port
|
local cln = socket.udp()
|
cln:setpeername("127.0.0.1",port)
|
cln:settimeout(2)
|
cln:send(protocol.client.greeting)
|
|
local msg = cln:receive()
|
if msg and msg:match(protocol.server.greeting:gsub("%%s",".+$")) then
|
local username = msg:match(protocol.server.greeting:gsub("%%s","(.+)$"))
|
if username ~= wx.wxGetUserId() then
|
ide:Print(("Another instance is running under user '%s' and can't be activated. This instance will continue running, which may cause interference with the debugger."):format(username))
|
else
|
local failed = false
|
for _, filename in ipairs(ide.filenames) do
|
cln:send(protocol.client.requestloading
|
:format(ide.cwd and GetFullPathIfExists(ide.cwd, filename) or filename))
|
|
local msg, err = cln:receive()
|
if msg ~= protocol.server.answerok then
|
failed = true
|
ide:Print(err,msg)
|
end
|
end
|
if #ide.filenames == 0 then -- no files are being loaded; just active the IDE
|
cln:send(protocol.client.show)
|
if cln:receive() ~= protocol.server.answerok then failed = true end
|
end
|
if failed then
|
ide:Print("Communication with the running instance failed, this instance will continue running.")
|
else -- done
|
os.exit(0)
|
end
|
end
|
else
|
ide:Print("The single instance communication has failed; there may be another instance running, which may cause interference with the debugger.")
|
end
|
end
|