Coverage Report

Created: 2018-09-25 14:53

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