Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "nsProfileLock.h"
7 : #include "nsCOMPtr.h"
8 : #include "nsQueryObject.h"
9 : #include "nsString.h"
10 :
11 : #if defined(XP_WIN)
12 : #include "ProfileUnlockerWin.h"
13 : #include "nsAutoPtr.h"
14 : #endif
15 :
16 : #if defined(XP_MACOSX)
17 : #include <Carbon/Carbon.h>
18 : #include <CoreFoundation/CoreFoundation.h>
19 : #endif
20 :
21 : #ifdef XP_UNIX
22 : #include <unistd.h>
23 : #include <fcntl.h>
24 : #include <errno.h>
25 : #include <signal.h>
26 : #include <stdlib.h>
27 : #include "prnetdb.h"
28 : #include "prsystem.h"
29 : #include "prenv.h"
30 : #include "mozilla/Printf.h"
31 : #endif
32 :
33 : #if defined(MOZ_WIDGET_GONK) && !defined(MOZ_CRASHREPORTER)
34 : #include <sys/syscall.h>
35 : #endif
36 :
37 : // **********************************************************************
38 : // class nsProfileLock
39 : //
40 : // This code was moved from profile/src/nsProfileAccess.
41 : // **********************************************************************
42 :
43 : #if defined (XP_UNIX)
44 : static bool sDisableSignalHandling = false;
45 : #endif
46 :
47 2 : nsProfileLock::nsProfileLock() :
48 : mHaveLock(false),
49 : mReplacedLockTime(0)
50 : #if defined (XP_WIN)
51 : ,mLockFileHandle(INVALID_HANDLE_VALUE)
52 : #elif defined (XP_UNIX)
53 : ,mPidLockFileName(nullptr)
54 2 : ,mLockFileDesc(-1)
55 : #endif
56 : {
57 : #if defined (XP_UNIX)
58 2 : next = prev = this;
59 2 : sDisableSignalHandling = PR_GetEnv("MOZ_DISABLE_SIG_HANDLER") ? true : false;
60 : #endif
61 2 : }
62 :
63 :
64 0 : nsProfileLock::nsProfileLock(nsProfileLock& src)
65 : {
66 0 : *this = src;
67 0 : }
68 :
69 :
70 0 : nsProfileLock& nsProfileLock::operator=(nsProfileLock& rhs)
71 : {
72 0 : Unlock();
73 :
74 0 : mHaveLock = rhs.mHaveLock;
75 0 : rhs.mHaveLock = false;
76 :
77 : #if defined (XP_WIN)
78 : mLockFileHandle = rhs.mLockFileHandle;
79 : rhs.mLockFileHandle = INVALID_HANDLE_VALUE;
80 : #elif defined (XP_UNIX)
81 0 : mLockFileDesc = rhs.mLockFileDesc;
82 0 : rhs.mLockFileDesc = -1;
83 0 : mPidLockFileName = rhs.mPidLockFileName;
84 0 : rhs.mPidLockFileName = nullptr;
85 0 : if (mPidLockFileName)
86 : {
87 : // rhs had a symlink lock, therefore it was on the list.
88 0 : PR_REMOVE_LINK(&rhs);
89 0 : PR_APPEND_LINK(this, &mPidLockList);
90 : }
91 : #endif
92 :
93 0 : return *this;
94 : }
95 :
96 :
97 0 : nsProfileLock::~nsProfileLock()
98 : {
99 0 : Unlock();
100 0 : }
101 :
102 :
103 : #if defined (XP_UNIX)
104 :
105 : static int setupPidLockCleanup;
106 :
107 : PRCList nsProfileLock::mPidLockList =
108 : PR_INIT_STATIC_CLIST(&nsProfileLock::mPidLockList);
109 :
110 0 : void nsProfileLock::RemovePidLockFiles(bool aFatalSignal)
111 : {
112 0 : while (!PR_CLIST_IS_EMPTY(&mPidLockList))
113 : {
114 0 : nsProfileLock *lock = static_cast<nsProfileLock*>(mPidLockList.next);
115 0 : lock->Unlock(aFatalSignal);
116 : }
117 0 : }
118 :
119 : static struct sigaction SIGHUP_oldact;
120 : static struct sigaction SIGINT_oldact;
121 : static struct sigaction SIGQUIT_oldact;
122 : static struct sigaction SIGILL_oldact;
123 : static struct sigaction SIGABRT_oldact;
124 : static struct sigaction SIGSEGV_oldact;
125 : static struct sigaction SIGTERM_oldact;
126 :
127 0 : void nsProfileLock::FatalSignalHandler(int signo
128 : #ifdef SA_SIGINFO
129 : , siginfo_t *info, void *context
130 : #endif
131 : )
132 : {
133 : // Remove any locks still held.
134 0 : RemovePidLockFiles(true);
135 :
136 : // Chain to the old handler, which may exit.
137 0 : struct sigaction *oldact = nullptr;
138 :
139 0 : switch (signo) {
140 : case SIGHUP:
141 0 : oldact = &SIGHUP_oldact;
142 0 : break;
143 : case SIGINT:
144 0 : oldact = &SIGINT_oldact;
145 0 : break;
146 : case SIGQUIT:
147 0 : oldact = &SIGQUIT_oldact;
148 0 : break;
149 : case SIGILL:
150 0 : oldact = &SIGILL_oldact;
151 0 : break;
152 : case SIGABRT:
153 0 : oldact = &SIGABRT_oldact;
154 0 : break;
155 : case SIGSEGV:
156 0 : oldact = &SIGSEGV_oldact;
157 0 : break;
158 : case SIGTERM:
159 0 : oldact = &SIGTERM_oldact;
160 0 : break;
161 : default:
162 0 : NS_NOTREACHED("bad signo");
163 0 : break;
164 : }
165 :
166 0 : if (oldact) {
167 0 : if (oldact->sa_handler == SIG_DFL) {
168 : // Make sure the default sig handler is executed
169 : // We need it to get Mozilla to dump core.
170 0 : sigaction(signo,oldact, nullptr);
171 :
172 : // Now that we've restored the default handler, unmask the
173 : // signal and invoke it.
174 :
175 : sigset_t unblock_sigs;
176 0 : sigemptyset(&unblock_sigs);
177 0 : sigaddset(&unblock_sigs, signo);
178 :
179 0 : sigprocmask(SIG_UNBLOCK, &unblock_sigs, nullptr);
180 :
181 0 : raise(signo);
182 : }
183 : #ifdef SA_SIGINFO
184 0 : else if (oldact->sa_sigaction &&
185 0 : (oldact->sa_flags & SA_SIGINFO) == SA_SIGINFO) {
186 0 : oldact->sa_sigaction(signo, info, context);
187 : }
188 : #endif
189 0 : else if (oldact->sa_handler && oldact->sa_handler != SIG_IGN)
190 : {
191 0 : oldact->sa_handler(signo);
192 : }
193 : }
194 :
195 : #ifdef MOZ_WIDGET_GONK
196 : switch (signo) {
197 : case SIGQUIT:
198 : case SIGILL:
199 : case SIGABRT:
200 : case SIGSEGV:
201 : #ifndef MOZ_CRASHREPORTER
202 : // Retrigger the signal for those that can generate a core dump
203 : signal(signo, SIG_DFL);
204 : if (info->si_code <= 0) {
205 : if (syscall(__NR_tgkill, getpid(), syscall(__NR_gettid), signo) < 0) {
206 : break;
207 : }
208 : }
209 : #endif
210 : return;
211 : default:
212 : break;
213 : }
214 : #endif
215 :
216 : // Backstop exit call, just in case.
217 0 : _exit(signo);
218 : }
219 :
220 1 : nsresult nsProfileLock::LockWithFcntl(nsIFile *aLockFile)
221 : {
222 1 : nsresult rv = NS_OK;
223 :
224 2 : nsAutoCString lockFilePath;
225 1 : rv = aLockFile->GetNativePath(lockFilePath);
226 1 : if (NS_FAILED(rv)) {
227 0 : NS_ERROR("Could not get native path");
228 0 : return rv;
229 : }
230 :
231 1 : aLockFile->GetLastModifiedTime(&mReplacedLockTime);
232 :
233 1 : mLockFileDesc = open(lockFilePath.get(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
234 1 : if (mLockFileDesc != -1)
235 : {
236 : struct flock lock;
237 1 : lock.l_start = 0;
238 1 : lock.l_len = 0; // len = 0 means entire file
239 1 : lock.l_type = F_WRLCK;
240 1 : lock.l_whence = SEEK_SET;
241 :
242 : // If fcntl(F_GETLK) fails then the server does not support/allow fcntl(),
243 : // return failure rather than access denied in this case so we fallback
244 : // to using a symlink lock, bug 303633.
245 1 : struct flock testlock = lock;
246 1 : if (fcntl(mLockFileDesc, F_GETLK, &testlock) == -1)
247 : {
248 0 : close(mLockFileDesc);
249 0 : mLockFileDesc = -1;
250 0 : rv = NS_ERROR_FAILURE;
251 : }
252 1 : else if (fcntl(mLockFileDesc, F_SETLK, &lock) == -1)
253 : {
254 0 : close(mLockFileDesc);
255 0 : mLockFileDesc = -1;
256 :
257 : // With OS X, on NFS, errno == ENOTSUP
258 : // XXX Check for that and return specific rv for it?
259 : #ifdef DEBUG
260 0 : printf("fcntl(F_SETLK) failed. errno = %d\n", errno);
261 : #endif
262 0 : if (errno == EAGAIN || errno == EACCES)
263 0 : rv = NS_ERROR_FILE_ACCESS_DENIED;
264 : else
265 0 : rv = NS_ERROR_FAILURE;
266 : }
267 : }
268 : else
269 : {
270 0 : NS_ERROR("Failed to open lock file.");
271 0 : rv = NS_ERROR_FAILURE;
272 : }
273 1 : return rv;
274 : }
275 :
276 0 : static bool IsSymlinkStaleLock(struct in_addr* aAddr, const char* aFileName,
277 : bool aHaveFcntlLock)
278 : {
279 : // the link exists; see if it's from this machine, and if
280 : // so if the process is still active
281 : char buf[1024];
282 0 : int len = readlink(aFileName, buf, sizeof buf - 1);
283 0 : if (len > 0)
284 : {
285 0 : buf[len] = '\0';
286 0 : char *colon = strchr(buf, ':');
287 0 : if (colon)
288 : {
289 0 : *colon++ = '\0';
290 0 : unsigned long addr = inet_addr(buf);
291 0 : if (addr != (unsigned long) -1)
292 : {
293 0 : if (colon[0] == '+' && aHaveFcntlLock) {
294 : // This lock was placed by a Firefox build which would have
295 : // taken the fnctl lock, and we've already taken the fcntl lock,
296 : // so the process that created this obsolete lock must be gone
297 0 : return true;
298 : }
299 :
300 0 : char *after = nullptr;
301 0 : pid_t pid = strtol(colon, &after, 0);
302 0 : if (pid != 0 && *after == '\0')
303 : {
304 0 : if (addr != aAddr->s_addr)
305 : {
306 : // Remote lock: give up even if stuck.
307 0 : return false;
308 : }
309 :
310 : // kill(pid,0) is a neat trick to check if a
311 : // process exists
312 0 : if (kill(pid, 0) == 0 || errno != ESRCH)
313 : {
314 : // Local process appears to be alive, ass-u-me it
315 : // is another Mozilla instance, or a compatible
316 : // derivative, that's currently using the profile.
317 : // XXX need an "are you Mozilla?" protocol
318 0 : return false;
319 : }
320 : }
321 : }
322 : }
323 : }
324 0 : return true;
325 : }
326 :
327 1 : nsresult nsProfileLock::LockWithSymlink(nsIFile *aLockFile, bool aHaveFcntlLock)
328 : {
329 : nsresult rv;
330 2 : nsAutoCString lockFilePath;
331 1 : rv = aLockFile->GetNativePath(lockFilePath);
332 1 : if (NS_FAILED(rv)) {
333 0 : NS_ERROR("Could not get native path");
334 0 : return rv;
335 : }
336 :
337 : // don't replace an existing lock time if fcntl already got one
338 1 : if (!mReplacedLockTime)
339 0 : aLockFile->GetLastModifiedTimeOfLink(&mReplacedLockTime);
340 :
341 : struct in_addr inaddr;
342 1 : inaddr.s_addr = htonl(INADDR_LOOPBACK);
343 :
344 : char hostname[256];
345 1 : PRStatus status = PR_GetSystemInfo(PR_SI_HOSTNAME, hostname, sizeof hostname);
346 1 : if (status == PR_SUCCESS)
347 : {
348 : char netdbbuf[PR_NETDB_BUF_SIZE];
349 : PRHostEnt hostent;
350 1 : status = PR_GetHostByName(hostname, netdbbuf, sizeof netdbbuf, &hostent);
351 1 : if (status == PR_SUCCESS)
352 1 : memcpy(&inaddr, hostent.h_addr, sizeof inaddr);
353 : }
354 :
355 : mozilla::SmprintfPointer signature =
356 : mozilla::Smprintf("%s:%s%lu", inet_ntoa(inaddr), aHaveFcntlLock ? "+" : "",
357 2 : (unsigned long)getpid());
358 1 : const char *fileName = lockFilePath.get();
359 1 : int symlink_rv, symlink_errno = 0, tries = 0;
360 :
361 : // use ns4.x-compatible symlinks if the FS supports them
362 1 : while ((symlink_rv = symlink(signature.get(), fileName)) < 0)
363 : {
364 0 : symlink_errno = errno;
365 0 : if (symlink_errno != EEXIST)
366 0 : break;
367 :
368 0 : if (!IsSymlinkStaleLock(&inaddr, fileName, aHaveFcntlLock))
369 0 : break;
370 :
371 : // Lock seems to be bogus: try to claim it. Give up after a large
372 : // number of attempts (100 comes from the 4.x codebase).
373 0 : (void) unlink(fileName);
374 0 : if (++tries > 100)
375 0 : break;
376 : }
377 :
378 1 : if (symlink_rv == 0)
379 : {
380 : // We exclusively created the symlink: record its name for eventual
381 : // unlock-via-unlink.
382 1 : rv = NS_OK;
383 1 : mPidLockFileName = strdup(fileName);
384 1 : if (mPidLockFileName)
385 : {
386 1 : PR_APPEND_LINK(this, &mPidLockList);
387 1 : if (!setupPidLockCleanup++)
388 : {
389 : // Clean up on normal termination.
390 : // This instanciates a dummy class, and will trigger the class
391 : // destructor when libxul is unloaded. This is equivalent to atexit(),
392 : // but gracefully handles dlclose().
393 1 : static RemovePidLockFilesExiting r;
394 :
395 : // Clean up on abnormal termination, using POSIX sigaction.
396 : // Don't arm a handler if the signal is being ignored, e.g.,
397 : // because mozilla is run via nohup.
398 1 : if (!sDisableSignalHandling) {
399 : struct sigaction act, oldact;
400 : #ifdef SA_SIGINFO
401 1 : act.sa_sigaction = FatalSignalHandler;
402 1 : act.sa_flags = SA_SIGINFO;
403 : #else
404 : act.sa_handler = FatalSignalHandler;
405 : #endif
406 1 : sigfillset(&act.sa_mask);
407 :
408 : #define CATCH_SIGNAL(signame) \
409 : PR_BEGIN_MACRO \
410 : if (sigaction(signame, nullptr, &oldact) == 0 && \
411 : oldact.sa_handler != SIG_IGN) \
412 : { \
413 : sigaction(signame, &act, &signame##_oldact); \
414 : } \
415 : PR_END_MACRO
416 :
417 1 : CATCH_SIGNAL(SIGHUP);
418 1 : CATCH_SIGNAL(SIGINT);
419 1 : CATCH_SIGNAL(SIGQUIT);
420 1 : CATCH_SIGNAL(SIGILL);
421 1 : CATCH_SIGNAL(SIGABRT);
422 1 : CATCH_SIGNAL(SIGSEGV);
423 1 : CATCH_SIGNAL(SIGTERM);
424 :
425 : #undef CATCH_SIGNAL
426 : }
427 : }
428 : }
429 : }
430 0 : else if (symlink_errno == EEXIST)
431 0 : rv = NS_ERROR_FILE_ACCESS_DENIED;
432 : else
433 : {
434 : #ifdef DEBUG
435 0 : printf("symlink() failed. errno = %d\n", errno);
436 : #endif
437 0 : rv = NS_ERROR_FAILURE;
438 : }
439 1 : return rv;
440 : }
441 : #endif /* XP_UNIX */
442 :
443 2 : nsresult nsProfileLock::GetReplacedLockTime(PRTime *aResult) {
444 2 : *aResult = mReplacedLockTime;
445 2 : return NS_OK;
446 : }
447 :
448 1 : nsresult nsProfileLock::Lock(nsIFile* aProfileDir,
449 : nsIProfileUnlocker* *aUnlocker)
450 : {
451 : #if defined (XP_MACOSX)
452 : NS_NAMED_LITERAL_STRING(LOCKFILE_NAME, ".parentlock");
453 : NS_NAMED_LITERAL_STRING(OLD_LOCKFILE_NAME, "parent.lock");
454 : #elif defined (XP_UNIX)
455 1 : NS_NAMED_LITERAL_STRING(OLD_LOCKFILE_NAME, "lock");
456 1 : NS_NAMED_LITERAL_STRING(LOCKFILE_NAME, ".parentlock");
457 : #else
458 : NS_NAMED_LITERAL_STRING(LOCKFILE_NAME, "parent.lock");
459 : #endif
460 :
461 : nsresult rv;
462 1 : if (aUnlocker)
463 1 : *aUnlocker = nullptr;
464 :
465 1 : NS_ENSURE_STATE(!mHaveLock);
466 :
467 : bool isDir;
468 1 : rv = aProfileDir->IsDirectory(&isDir);
469 1 : if (NS_FAILED(rv))
470 0 : return rv;
471 1 : if (!isDir)
472 0 : return NS_ERROR_FILE_NOT_DIRECTORY;
473 :
474 2 : nsCOMPtr<nsIFile> lockFile;
475 1 : rv = aProfileDir->Clone(getter_AddRefs(lockFile));
476 1 : if (NS_FAILED(rv))
477 0 : return rv;
478 :
479 1 : rv = lockFile->Append(LOCKFILE_NAME);
480 1 : if (NS_FAILED(rv))
481 0 : return rv;
482 :
483 : // Remember the name we're using so we can clean up
484 1 : rv = lockFile->Clone(getter_AddRefs(mLockFile));
485 1 : if (NS_FAILED(rv))
486 0 : return rv;
487 :
488 : #if defined(XP_MACOSX)
489 : // First, try locking using fcntl. It is more reliable on
490 : // a local machine, but may not be supported by an NFS server.
491 :
492 : rv = LockWithFcntl(lockFile);
493 : if (NS_FAILED(rv) && (rv != NS_ERROR_FILE_ACCESS_DENIED))
494 : {
495 : // If that failed for any reason other than NS_ERROR_FILE_ACCESS_DENIED,
496 : // assume we tried an NFS that does not support it. Now, try with symlink.
497 : rv = LockWithSymlink(lockFile, false);
498 : }
499 :
500 : if (NS_SUCCEEDED(rv))
501 : {
502 : // Check for the old-style lock used by pre-mozilla 1.3 builds.
503 : // Those builds used an earlier check to prevent the application
504 : // from launching if another instance was already running. Because
505 : // of that, we don't need to create an old-style lock as well.
506 : struct LockProcessInfo
507 : {
508 : ProcessSerialNumber psn;
509 : unsigned long launchDate;
510 : };
511 :
512 : PRFileDesc *fd = nullptr;
513 : int32_t ioBytes;
514 : ProcessInfoRec processInfo;
515 : LockProcessInfo lockProcessInfo;
516 :
517 : rv = lockFile->SetLeafName(OLD_LOCKFILE_NAME);
518 : if (NS_FAILED(rv))
519 : return rv;
520 : rv = lockFile->OpenNSPRFileDesc(PR_RDONLY, 0, &fd);
521 : if (NS_SUCCEEDED(rv))
522 : {
523 : ioBytes = PR_Read(fd, &lockProcessInfo, sizeof(LockProcessInfo));
524 : PR_Close(fd);
525 :
526 : if (ioBytes == sizeof(LockProcessInfo))
527 : {
528 : #ifdef __LP64__
529 : processInfo.processAppRef = nullptr;
530 : #else
531 : processInfo.processAppSpec = nullptr;
532 : #endif
533 : processInfo.processName = nullptr;
534 : processInfo.processInfoLength = sizeof(ProcessInfoRec);
535 : if (::GetProcessInformation(&lockProcessInfo.psn, &processInfo) == noErr &&
536 : processInfo.processLaunchDate == lockProcessInfo.launchDate)
537 : {
538 : return NS_ERROR_FILE_ACCESS_DENIED;
539 : }
540 : }
541 : else
542 : {
543 : NS_WARNING("Could not read lock file - ignoring lock");
544 : }
545 : }
546 : rv = NS_OK; // Don't propagate error from OpenNSPRFileDesc.
547 : }
548 : #elif defined(XP_UNIX)
549 : // Get the old lockfile name
550 2 : nsCOMPtr<nsIFile> oldLockFile;
551 1 : rv = aProfileDir->Clone(getter_AddRefs(oldLockFile));
552 1 : if (NS_FAILED(rv))
553 0 : return rv;
554 1 : rv = oldLockFile->Append(OLD_LOCKFILE_NAME);
555 1 : if (NS_FAILED(rv))
556 0 : return rv;
557 :
558 : // First, try locking using fcntl. It is more reliable on
559 : // a local machine, but may not be supported by an NFS server.
560 1 : rv = LockWithFcntl(lockFile);
561 1 : if (NS_SUCCEEDED(rv)) {
562 : // Check to see whether there is a symlink lock held by an older
563 : // Firefox build, and also place our own symlink lock --- but
564 : // mark it "obsolete" so that other newer builds can break the lock
565 : // if they obtain the fcntl lock
566 1 : rv = LockWithSymlink(oldLockFile, true);
567 :
568 : // If the symlink failed for some reason other than it already
569 : // exists, then something went wrong e.g. the file system
570 : // doesn't support symlinks, or we don't have permission to
571 : // create a symlink there. In such cases we should just
572 : // continue because it's unlikely there is an old build
573 : // running with a symlink there and we've already successfully
574 : // placed a fcntl lock.
575 1 : if (rv != NS_ERROR_FILE_ACCESS_DENIED)
576 1 : rv = NS_OK;
577 : }
578 0 : else if (rv != NS_ERROR_FILE_ACCESS_DENIED)
579 : {
580 : // If that failed for any reason other than NS_ERROR_FILE_ACCESS_DENIED,
581 : // assume we tried an NFS that does not support it. Now, try with symlink
582 : // using the old symlink path
583 0 : rv = LockWithSymlink(oldLockFile, false);
584 : }
585 :
586 : #elif defined(XP_WIN)
587 : nsAutoString filePath;
588 : rv = lockFile->GetPath(filePath);
589 : if (NS_FAILED(rv))
590 : return rv;
591 :
592 : lockFile->GetLastModifiedTime(&mReplacedLockTime);
593 :
594 : // always create the profile lock and never delete it so we can use its
595 : // modification timestamp to detect startup crashes
596 : mLockFileHandle = CreateFileW(filePath.get(),
597 : GENERIC_READ | GENERIC_WRITE,
598 : 0, // no sharing - of course
599 : nullptr,
600 : CREATE_ALWAYS,
601 : 0,
602 : nullptr);
603 : if (mLockFileHandle == INVALID_HANDLE_VALUE) {
604 : if (aUnlocker) {
605 : RefPtr<mozilla::ProfileUnlockerWin> unlocker(
606 : new mozilla::ProfileUnlockerWin(filePath));
607 : if (NS_SUCCEEDED(unlocker->Init())) {
608 : nsCOMPtr<nsIProfileUnlocker> unlockerInterface(
609 : do_QueryObject(unlocker));
610 : unlockerInterface.forget(aUnlocker);
611 : }
612 : }
613 : return NS_ERROR_FILE_ACCESS_DENIED;
614 : }
615 : #endif
616 :
617 1 : if (NS_SUCCEEDED(rv))
618 1 : mHaveLock = true;
619 :
620 1 : return rv;
621 : }
622 :
623 :
624 0 : nsresult nsProfileLock::Unlock(bool aFatalSignal)
625 : {
626 0 : nsresult rv = NS_OK;
627 :
628 0 : if (mHaveLock)
629 : {
630 : #if defined (XP_WIN)
631 : if (mLockFileHandle != INVALID_HANDLE_VALUE)
632 : {
633 : CloseHandle(mLockFileHandle);
634 : mLockFileHandle = INVALID_HANDLE_VALUE;
635 : }
636 : #elif defined (XP_UNIX)
637 0 : if (mPidLockFileName)
638 : {
639 0 : PR_REMOVE_LINK(this);
640 0 : (void) unlink(mPidLockFileName);
641 :
642 : // Only free mPidLockFileName if we're not in the fatal signal
643 : // handler. The problem is that a call to free() might be the
644 : // cause of this fatal signal. If so, calling free() might cause
645 : // us to wait on the malloc implementation's lock. We're already
646 : // holding this lock, so we'll deadlock. See bug 522332.
647 0 : if (!aFatalSignal)
648 0 : free(mPidLockFileName);
649 0 : mPidLockFileName = nullptr;
650 : }
651 0 : if (mLockFileDesc != -1)
652 : {
653 0 : close(mLockFileDesc);
654 0 : mLockFileDesc = -1;
655 : // Don't remove it
656 : }
657 : #endif
658 :
659 0 : mHaveLock = false;
660 : }
661 :
662 0 : return rv;
663 : }
664 :
665 0 : nsresult nsProfileLock::Cleanup()
666 : {
667 0 : if (mLockFile) {
668 0 : return mLockFile->Remove(false);
669 : }
670 :
671 0 : return NS_OK;
672 : }
|