Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/ipc/glue/FileDescriptorUtils.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "FileDescriptorUtils.h"
8
9
#include "nsIEventTarget.h"
10
11
#include "nsCOMPtr.h"
12
#include "nsDebug.h"
13
#include "nsNetCID.h"
14
#include "nsServiceManagerUtils.h"
15
#include "nsThreadUtils.h"
16
#include "prio.h"
17
#include "private/pprio.h"
18
19
#include <errno.h>
20
#ifdef XP_WIN
21
#include <io.h>
22
#else
23
#include <unistd.h>
24
#endif
25
26
using mozilla::ipc::CloseFileRunnable;
27
28
#ifdef DEBUG
29
30
CloseFileRunnable::CloseFileRunnable(const FileDescriptor& aFileDescriptor)
31
: mFileDescriptor(aFileDescriptor)
32
{
33
  MOZ_ASSERT(aFileDescriptor.IsValid());
34
}
35
36
#endif // DEBUG
37
38
CloseFileRunnable::~CloseFileRunnable()
39
0
{
40
0
  if (mFileDescriptor.IsValid()) {
41
0
    // It's probably safer to take the main thread IO hit here rather than leak
42
0
    // the file descriptor.
43
0
    CloseFile();
44
0
  }
45
0
}
46
47
NS_IMPL_ISUPPORTS(CloseFileRunnable, nsIRunnable)
48
49
void
50
CloseFileRunnable::Dispatch()
51
0
{
52
0
  nsCOMPtr<nsIEventTarget> eventTarget =
53
0
    do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
54
0
  NS_ENSURE_TRUE_VOID(eventTarget);
55
0
56
0
  nsresult rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
57
0
  NS_ENSURE_SUCCESS_VOID(rv);
58
0
}
59
60
void
61
CloseFileRunnable::CloseFile()
62
0
{
63
0
  // It's possible for this to happen on the main thread if the dispatch to the
64
0
  // stream service fails so we can't assert the thread on which we're running.
65
0
  mFileDescriptor = FileDescriptor();
66
0
}
67
68
NS_IMETHODIMP
69
CloseFileRunnable::Run()
70
0
{
71
0
  MOZ_ASSERT(!NS_IsMainThread());
72
0
73
0
  CloseFile();
74
0
  return NS_OK;
75
0
}
76
77
namespace mozilla {
78
namespace ipc {
79
80
FILE*
81
FileDescriptorToFILE(const FileDescriptor& aDesc,
82
                     const char* aOpenMode)
83
0
{
84
0
  if (!aDesc.IsValid()) {
85
0
    errno = EBADF;
86
0
    return nullptr;
87
0
  }
88
0
  auto handle = aDesc.ClonePlatformHandle();
89
#ifdef XP_WIN
90
  int fd = _open_osfhandle(static_cast<intptr_t>(handle.get()), 0);
91
  if (fd == -1) {
92
    return nullptr;
93
  }
94
  Unused << handle.release();
95
#else
96
  int fd = handle.release();
97
0
#endif
98
0
  FILE* file = fdopen(fd, aOpenMode);
99
0
  if (!file) {
100
0
    int saved_errno = errno;
101
0
    close(fd);
102
0
    errno = saved_errno;
103
0
  }
104
0
  return file;
105
0
}
106
107
FileDescriptor
108
FILEToFileDescriptor(FILE* aStream)
109
0
{
110
0
  if (!aStream) {
111
0
    errno = EBADF;
112
0
    return FileDescriptor();
113
0
  }
114
#ifdef XP_WIN
115
  int fd = _fileno(aStream);
116
  if (fd == -1) {
117
    return FileDescriptor();
118
  }
119
  return FileDescriptor(reinterpret_cast<HANDLE>(_get_osfhandle(fd)));
120
#else
121
0
  return FileDescriptor(fileno(aStream));
122
0
#endif
123
0
}
124
125
} // namespace ipc
126
} // namespace mozilla