source: filezilla/trunk/fuentes/src/interface/ipcmutex.cpp @ 3185

Last change on this file since 3185 was 3185, checked in by jrpelegrina, 2 years ago

Update new version: 3.15.02

File size: 3.9 KB
Line 
1#include <filezilla.h>
2#include "ipcmutex.h"
3#include "Options.h"
4
5#ifndef __WXMSW__
6#include <errno.h>
7int CInterProcessMutex::m_fd = -1;
8int CInterProcessMutex::m_instanceCount = 0;
9#endif
10
11std::list<CReentrantInterProcessMutexLocker::t_data> CReentrantInterProcessMutexLocker::m_mutexes;
12
13CInterProcessMutex::CInterProcessMutex(enum t_ipcMutexType mutexType, bool initialLock /*=true*/)
14{
15        m_locked = false;
16#ifdef __WXMSW__
17        // Create mutex_
18        hMutex = ::CreateMutex(0, false, wxString::Format(_T("FileZilla 3 Mutex Type %d"), mutexType).wc_str());
19#else
20        if (!m_instanceCount) {
21                // Open file only if this is the first instance
22                wxFileName fn(COptions::Get()->GetOption(OPTION_DEFAULT_SETTINGSDIR), _T("lockfile"));
23                m_fd = open(fn.GetFullPath().mb_str(), O_CREAT | O_RDWR | O_CLOEXEC, 0644);
24        }
25        m_instanceCount++;
26#endif
27        m_type = mutexType;
28        if (initialLock)
29                Lock();
30}
31
32CInterProcessMutex::~CInterProcessMutex()
33{
34        if (m_locked)
35                Unlock();
36#ifdef __WXMSW__
37        if (hMutex)
38                ::CloseHandle(hMutex);
39#else
40        m_instanceCount--;
41        // Close file only if this is the last instance. At least under
42        // Linux, closing the lock file has the affect of removing all locks.
43        if (!m_instanceCount && m_fd >= 0)
44                close(m_fd);
45#endif
46}
47
48bool CInterProcessMutex::Lock()
49{
50        wxASSERT(!m_locked);
51#ifdef __WXMSW__
52        if (hMutex)
53                ::WaitForSingleObject(hMutex, INFINITE);
54#else
55        if (m_fd >= 0)
56        {
57                // Lock 1 byte region in the lockfile. m_type specifies the byte to lock.
58                struct flock f = {};
59                f.l_type = F_WRLCK;
60                f.l_whence = SEEK_SET;
61                f.l_start = m_type;
62                f.l_len = 1;
63                f.l_pid = getpid();
64
65                while (fcntl(m_fd, F_SETLKW, &f) == -1)
66                {
67                        if (errno == EINTR) // Interrupted by signal, retry
68                                continue;
69
70                        // Can't do any locking in this case
71                        return false;
72                }
73        }
74#endif
75
76        m_locked = true;
77
78        return true;
79}
80
81int CInterProcessMutex::TryLock()
82{
83        wxASSERT(!m_locked);
84
85#ifdef __WXMSW__
86        if (!hMutex)
87        {
88                m_locked = false;
89                return 0;
90        }
91
92        int res = ::WaitForSingleObject(hMutex, 1);
93        if (res == WAIT_OBJECT_0)
94        {
95                m_locked = true;
96                return 1;
97        }
98#else
99        if (m_fd >= 0)
100        {
101                // Try to lock 1 byte region in the lockfile. m_type specifies the byte to lock.
102                struct flock f = {};
103                f.l_type = F_WRLCK;
104                f.l_whence = SEEK_SET;
105                f.l_start = m_type;
106                f.l_len = 1;
107                f.l_pid = getpid();
108                while (fcntl(m_fd, F_SETLK, &f) == -1)
109                {
110                        if (errno == EINTR) // Interrupted by signal, retry
111                                continue;
112
113                        if (errno == EAGAIN || errno == EACCES) // Lock held by other process
114                                return 0;
115
116                        // Can't do any locking in this case
117                        return -1;
118                }
119
120                m_locked = true;
121                return 1;
122        }
123#endif
124
125        return 0;
126}
127
128void CInterProcessMutex::Unlock()
129{
130        if (!m_locked)
131                return;
132        m_locked = false;
133
134#ifdef __WXMSW__
135        if (hMutex)
136                ::ReleaseMutex(hMutex);
137#else
138        if (m_fd >= 0)
139        {
140                // Unlock region specified by m_type.
141                struct flock f = {};
142                f.l_type = F_UNLCK;
143                f.l_whence = SEEK_SET;
144                f.l_start = m_type;
145                f.l_len = 1;
146                f.l_pid = getpid();
147                while (fcntl(m_fd, F_SETLKW, &f) == -1)
148                {
149                        if (errno == EINTR) // Interrupted by signal, retry
150                                continue;
151
152                        // Can't do any locking in this case
153                        return;
154                }
155        }
156#endif
157}
158
159CReentrantInterProcessMutexLocker::CReentrantInterProcessMutexLocker(enum t_ipcMutexType mutexType)
160{
161        m_type = mutexType;
162
163        std::list<t_data>::iterator iter;
164        for (iter = m_mutexes.begin(); iter != m_mutexes.end(); ++iter)
165        {
166                if (iter->pMutex->GetType() == mutexType)
167                        break;
168        }
169
170        if (iter != m_mutexes.end())
171        {
172                iter->lockCount++;
173        }
174        else
175        {
176                t_data data;
177                data.lockCount = 1;
178                data.pMutex = new CInterProcessMutex(mutexType);
179                m_mutexes.push_back(data);
180        }
181}
182
183CReentrantInterProcessMutexLocker::~CReentrantInterProcessMutexLocker()
184{
185        std::list<t_data>::iterator iter;
186        for (iter = m_mutexes.begin(); iter != m_mutexes.end(); ++iter)
187        {
188                if (iter->pMutex->GetType() == m_type)
189                        break;
190        }
191
192        wxASSERT(iter != m_mutexes.end());
193        if (iter == m_mutexes.end())
194                return;
195
196        if (iter->lockCount == 1)
197        {
198                delete iter->pMutex;
199                m_mutexes.erase(iter);
200        }
201        else
202                iter->lockCount--;
203}
Note: See TracBrowser for help on using the repository browser.