Ticket #2165 (closed defect: fixed)

Opened 2 years ago

Last modified 2 years ago

pid file behavior

Reported by: m. dietrich <mdt@…> Owned by: asterix
Priority: normal Milestone: 0.11
Component: None Version:
Severity: normal Keywords:
Cc: OS:

Description

gajim complains on startup that another instance is running while we are just after a boot. the pid-file is not deleted when i logout from a gnome session (it is deleted when shutting down gajim with its menu entry).

also the pidfile does not contain a pid... strange, it's size zero here. so gajim has no chance to see if the pid is already there and a running gajim.

why isn't dbus (if avaiable) used to see if a running gajim can be found?

Attachments

Change History

Changed 2 years ago by bb

  • summary changed from pid-file behavior strange to fixed?

lines 172-174 from src/gajim.py:

# Create pid file f = open(pid_filename, 'a') f.close()

it seems the pid file just needs to exist. they don't actually store the pid itself in there. I propose we change those lines to:

#obviously, assuming os is imported pid=os.getpid().str() f = open(pid_filename, 'w') #(why append?) f.write(pid) f.close()

now, we actually have a pid in the pid file ;) and, if you want to kill the program, just check out that pid and do: $ kill 12345

no need for any weird jumps n bumps.

Changed 2 years ago by bb

argh! trac's a bitch... it killed my newlines! wtf. again:

from:

 # Create pid file
 f = open(pid_filename, 'a')
 f.close()

to:

 #obviously, assuming os is imported
 pid=os.getpid().__str__()
 f = open(pid_filename, 'w')  #(why append?)
 f.write(pid)
 f.close()

Changed 2 years ago by asterix

if you have this message at startup of gajim, this means your Gajim has

closed improperly. Maybe gnome session sends a kill -9 instead of a simple kill ?

why we don't use DBUS ? it doesn't work under windows

problem with pid file that contain the real pid. At restart, you restart gajim, it detects a pid in the file, so it kiils it. problem: it may be another process now, so you kill your browser by starting Gajim ...

to keep that in mind in case we need it, we can kill a process in one of those way:

 PROCESS_TERMINATE = 1
 handle = win32api.OpenProcess(PROCESS_TERMINATE, False, pid)
 win32api.TerminateProcess(handle, -1)
 win32api.CloseHandle(handle)

or

 os.popen('TASKKILL /PID '+str(pid)+' /F')

Changed 2 years ago by bb

you don't need to let gajim kill it. actually; you shouldn't... why would

you want to kill it? even if it actually IS another instance of gajim, you don't want to just kill it because a second one is being started... this is just to let the user know what the pid of the last gajim was. he can check for himself (with $ ps -A | grep 12345 for example) if it's really gajim and then choose to kill it. or not.

Changed 2 years ago by m. dietrich <mdt@…>

  • summary changed from fixed? to pid file behavior

i don't know what gnome sends on logout but i don't think so - i will

check that.

i did not mean to kill the other process. i would lookup if a process with that id exists and eventually check if it has 'gajim' in the commandline. if so and only if tell the user that gajim may already be running. otherwise assume no other gajim is running.

dbus could be used only if avaiable.

perhaps a config setting could switch off pid file usage entirely...

Changed 2 years ago by m. dietrich <mdt@…>

this bug seems a dublicate of #2028...

here is my (unix-) fix in gajim.py:

 #!python
  190 import atexit
  191 atexit.register(on_exit)
  192 try:
  193     import signal
  194     def sighdl(num, frm): on_exit()
  195     signal.signal(signal.SIGQUIT, sighdl)
  196     signal.signal(signal.SIGHUP, sighdl)
  197     signal.signal(signal.SIGTERM, sighdl)
  198 except ImportError:
  199     pass
  200
  201 parser = optparser.OptionsParser(config_filename)

Changed 2 years ago by asterix

sounds a good idea to show dialog only if such a process which name contain gajim exists. Here is a link to list process under win:

http://mail.python.org/pipermail/python-win32/2003-December/001482.html

about your patch, you knw the signal that gnome sends to gajim ?isn't it a simple kill ?

Changed 2 years ago by m. dietrich <mdt@…>

i am very sorry to tell, that gnome does not send a signal in all cases. i would recommend the pid way of checking if gajim is already running. if the pid-file contains the pid, this is very easy:

i gajim.py line 171 i would insert:

# Create pid file
f = open(pid_filename, 'a') 
f.write(str(os.getpid()))
f.close()

now the file has the pid which can easily be tested as follows. for linux you may insert for process alive detection (instead of line 151 in same file):

import dialogs
def pid_alive():
    try: 
        pf = open(pid_filename)
        pid = int(pf.read().strip())
        pf.close()
        f = open('/proc/%d/status'% pid) 
        n = f.readline()
        f.close()
        n = n.split()[1].strip()
        if n == 'gajim':
            return True 
    except:
        pass
    return False

if pid_alive():
    path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps/gajim.png')

for windows i can't help :(

Changed 2 years ago by asterix

  • status changed from new to closed
  • resolution set to fixed
  • milestone set to 0.11

(In [7518]) better pid behaviour. we now in process list if pid contained in gajim.pid is still gajim. fixes #2165. (Linux only)

Changed 2 years ago by junglecow

Just in case anyone wants to have a go at the Windows bit… Read about process list in Windows.

Changed 2 years ago by m. dietrich <mdt@…>

hi, i played around a little bit with windows (what a pain) and found out that the solution mentioned above using wmi is a bit complicated because of the setup of dcom for python. i found a simpler way to get a process name by pid:

from ctypes import (windll, c_ulong, c_int, Structure, c_char, POINTER, pointer, )

class PROCESSENTRY32(Structure):
	_fields_ = [
		('dwSize', c_ulong, ),
		('cntUsage', c_ulong, ),
		('th32ProcessID', c_ulong, ),
		('th32DefaultHeapID', c_ulong, ),
		('th32ModuleID', c_ulong, ),
		('cntThreads', c_ulong, ),
		('th32ParentProcessID', c_ulong, ),
		('pcPriClassBase', c_ulong, ),
		('dwFlags', c_ulong, ),
		('szExeFile', c_char*512, ),
		]
	def __init__(self):
		Structure.__init__(self, 512+9*4)

k = windll.kernel32
k.CreateToolhelp32Snapshot.argtypes = c_ulong, c_ulong,
k.CreateToolhelp32Snapshot.restype = c_int
k.Process32First.argtypes = c_int, POINTER(PROCESSENTRY32),
k.Process32First.restype = c_int
k.Process32Next.argtypes = c_int, POINTER(PROCESSENTRY32),
k.Process32Next.restype = c_int

def get_p(p):
	h = k.CreateToolhelp32Snapshot(2, 0) # TH32CS_SNAPPROCESS
	assert h > 0, 'CreateToolhelp32Snapshot failed'
	b = pointer(PROCESSENTRY32())
	f = k.Process32First(h, b)
	while f:
		if b.contents.th32ProcessID == p:
			return b.contents.szExeFile
		f = k.Process32Next(h, b)

from os import getpid
print get_p(getpid())

this is just using ctypes (coming with py 2.5 anyway) but gives only the .exe, python.exe in our case. no hint for gajim. while ctypes really makes things easy i did not find the function in windows to get the process arguments.

Changed 2 years ago by asterix

(In [7647]) [mdt] better pid file behaviour for windows. fixes #2165

Add/Change #2165 (pid file behavior)

Author



Change Properties
<Author field>
Action
as closed
Next status will be 'reopened'
 
Note: See TracTickets for help on using tickets.