]>
git.saurik.com Git - apple/libc.git/blob - libdarwin/h/cleanup.h
2 * Copyright (c) 2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 * Attributes to handle automatic clean-up of certain types of variables when
27 * they go out of scope.
29 * IMPORTANT: These attributes will NOT cause a variable to be cleaned up when
30 * its value changes. For example, this pattern would leak:
32 * void *__os_free ptr = malloc(10);
33 * ptr = somewhere_else;
36 * You should only use these attributes for very well-scoped, temporary
39 #ifndef __DARWIN_CLEANUP_H
40 #define __DARWIN_CLEANUP_H
44 #include <os/assumes.h>
45 #include <os/object_private.h>
48 #include <sys/errno.h>
49 #include <sys/cdefs.h>
55 #include <mach/mach_init.h>
56 #include <mach/port.h>
57 #include <mach/mach_port.h>
58 #include <mach/kern_return.h>
59 #include <mach/mach_right.h>
67 #if __has_attribute(cleanup)
70 * An attribute that may be applied to a variable's type. This attribute causes
71 * the variable to be passed to free(3) when it goes out of scope. Applying this
72 * attribute to variables that do not reference heap allocations will result in
75 #define __os_free __attribute__((cleanup(__os_cleanup_free)))
77 __os_cleanup_free(void *__p
)
79 void **tp
= (void **)__p
;
86 * An attribute that may be applied to a variable's type. This attribute causes
87 * the variable to be passed to close(2) when it goes out of scope. Applying
88 * this attribute to variables that do not reference a valid file descriptor
89 * will result in undefined behavior. If the variable's value is -1 upon going
90 * out-of-scope, no cleanup is performed.
92 #define __os_close __attribute__((cleanup(__os_cleanup_close)))
94 __os_cleanup_close(int *__fd
)
100 posix_assert_zero(close(fd
));
104 * @define __os_fclose
105 * An attribute that may be applied to a variable's type. This attribute causes
106 * the variable to be passed to fclose(3) when it goes out of scope. Applying
107 * this attribute to variables that do not reference a valid FILE * will result
108 * in undefined behavior. If the variable's value is NULL upon going out-of-
109 * scope, no cleanup is performed.
111 #define __os_fclose __attribute__((cleanup(__os_cleanup_fclose)))
113 __os_cleanup_fclose(FILE **__fp
)
124 os_assert_zero(errno
);
129 * @define __os_closedir
130 * An attribute that may be applied to a variable's type. This attribute causes
131 * the variable to be passed to closedir(3) when it goes out of scope. Applying
132 * this attribute to variables that do not reference a valid DIR * will result
133 * in undefined behavior. If the variable's value is NULL upon going out-of-
134 * scope, no cleanup is performed.
136 #define __os_closedir __attribute__((cleanup(__os_cleanup_closedir)))
138 __os_cleanup_closedir(DIR **__dp
)
145 posix_assert_zero(closedir(dp
));
149 * @define __os_close_mach_recv
150 * An attribute that may be applied to a variable's type. This attribute causes
151 * the variable to be wrapped in a mach receive right object and passed to
152 * {@link mach_right_recv_destruct} when it goes out of scope. Applying this
153 * attribute to variables that do not reference a valid Mach port receive right
154 * will result in undefined behavior. If the variable's value is MACH_PORT_NULL
155 * or MACH_PORT_DEAD upon going out-of-scope, no cleanup is performed.
157 #define __os_close_mach_recv \
158 __attribute__((cleanup(__os_cleanup_close_mach_recv)))
160 __os_cleanup_close_mach_recv(mach_port_t
*__p
)
162 mach_port_t p
= *__p
;
163 mach_right_recv_t mr
= mach_right_recv(p
);
165 if (!MACH_PORT_VALID(p
)) {
169 mach_right_recv_destruct(mr
, NULL
, 0);
173 * @define __os_release_mach_send
174 * An attribute that may be applied to a variable's type. This attribute causes
175 * the variable to be wrapped in a mach send right object and passed to
176 * {@link mach_right_send_release} when it goes out of scope. Applying this
177 * attribute to variables that do not reference a valid Mach port send right or
178 * MACH_PORT_NULL or MACH_PORT_DEAD will result in undefined behavior. If the
179 * variable's value is MACH_PORT_NULL or MACH_PORT_DEAD upon going out-of-scope,
180 * no cleanup is performed.
182 #define __os_release_mach_send \
183 __attribute__((cleanup(__os_cleanup_release_mach_send)))
185 __os_cleanup_release_mach_send(mach_port_t
*__p
)
187 mach_port_t p
= *__p
;
188 mach_right_send_t ms
= mach_right_send(p
);
190 if (!MACH_PORT_VALID(p
)) {
194 mach_right_send_release(ms
);
198 * @define __os_preserve_errno
199 * An attribute that may be applied to a variable's type. This attribute sets
200 * the global errno to the value of the variable when the variable goes out of
201 * scope. This attribute is useful for preserving the value of errno upon entry
202 * to a function and guaranteeing that it is restored upon exit.
204 #define __os_preserve_errno \
205 __unused __attribute__((cleanup(__os_cleanup_errno)))
207 __os_cleanup_errno(int *__e
)
213 * @define __os_release
214 * An attribute that may be applied to a variable's type. This attribute causes
215 * the variable to be passed to os_release() when it goes out of scope. Applying
216 * this attribute to a variable which does not reference a valid os_object_t
217 * object will result in undefined behavior. If the variable's value is NULL
218 * upon going out-of-scope, no cleanup is performed.
220 * This attribute may be applied to dispatch and XPC objects.
222 * When compiling with ARC, this attribute does nothing.
224 #if __has_feature(objc_arc)
227 #define __os_release __attribute__((cleanup(__os_cleanup_os_release)))
229 __os_cleanup_os_release(void *__p
)
231 _os_object_t
*tp
= (_os_object_t
*)__p
;
232 _os_object_t o
= *tp
;
240 #if DARWIN_CLEANUP_CF
242 * @define __os_cfrelease
243 * An attribute that may be applied to a variable's type. This attribute causes
244 * the variable to be passed to CFRelease() when it goes out of scope. Applying
245 * this attribute to a variable which does not reference a valid CoreFoundation
246 * object will result in undefined behavior. If the variable's value is NULL
247 * upon going out-of-scope, no cleanup is performed.
249 * In order to use, you must define the DARWIN_CLEANUP_CF macro to 1 prior to
250 * including this header.
252 #define __os_cfrelease __attribute__((cleanup(__os_cleanup_cfrelease)))
254 __os_cleanup_cfrelease(void *__p
)
256 CFTypeRef
*tp
= (CFTypeRef
*)__p
;
263 #endif // DARWIN_CLEANUP_CF
265 #if DARWIN_CLEANUP_IOKIT
267 * @define __os_iorelease
268 * An attribute that may be applied to a variable's type. This attribute causes
269 * the variable to be passed to IOObjectRelease() when it goes out of scope.
270 * Applying this attribute to a variable which does not reference a valid IOKit
271 * object will result in undefined behavior. If the variable's value is
272 * IO_OBJECT_NULL upon going out-of-scope, no cleanup is performed.
275 * In order to use, you must define the DARWIN_CLEANUP_IOKIT macro to 1 prior to
276 * including this header.
278 #define __os_iorelease __attribute__((cleanup(__os_cleanup_iorelease)))
280 __os_cleanup_iorelease(void *__p
)
282 kern_return_t kr
= KERN_FAILURE
;
283 io_object_t
*iop
= (io_object_t
*)__p
;
284 io_object_t io
= *iop
;
286 if (io
== IO_OBJECT_NULL
) {
290 kr
= IOObjectRelease(io
);
292 os_crash("IOObjectRetain: %{mach.errno}d", kr
);
297 * @define __os_ioclose
298 * An attribute that may be applied to a variable's type. This attribute causes
299 * the variable to be passed to IOServiceClose() when it goes out of scope.
300 * Applying this attribute to a variable which does not reference a valid IOKit
301 * connection will result in undefined behavior. If the variable's value is
302 * IO_OBJECT_NULL upon going out-of-scope, no cleanup is performed.
304 * In order to use, you must define the DARWIN_CLEANUP_IOKIT macro to 1 prior to
305 * including this header.
307 #define __os_ioclose __attribute__((cleanup(__os_cleanup_ioclose)))
309 __os_cleanup_ioclose(void *__p
)
311 kern_return_t kr
= KERN_FAILURE
;
312 io_connect_t
*iop
= (io_object_t
*)__p
;
313 io_connect_t io
= *iop
;
315 if (io
== IO_OBJECT_NULL
) {
319 kr
= IOServiceClose(io
);
321 os_crash("IOObjectRelease: %{mach.errno}d", kr
);
324 #endif // DARWIN_CLEANUP_IOKIT
327 * @define __os_unfair_unlock
328 * An attribute that may be applied to a variable's type. This attribute causes
329 * the variable to be passed to os_unfair_lock_unlock() when it goes out of
330 * scope. Applying this attribute to a variable which does not reference a valid
331 * os_unfair_lock_t object will result in undefined behavior. If the variable's
332 * value is NULL upon going out-of-scope, no cleanup is performed.
334 * This attribute is useful even when the target lock is taken conditionally via
335 * the following pattern:
337 * os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
338 * os_unfair_lock_t __os_unfair_unlock l2un = NULL;
340 * if (take_the_lock) {
341 * os_unfair_lock_lock(&lock);
343 * // Guarantee that 'lock' will be unconditionally released when the
344 * // scope containing 'l2un' ends.
348 #define __os_unfair_unlock __attribute__((cleanup(__os_cleanup_unfair_unlock)))
350 __os_cleanup_unfair_unlock(void *__p
)
352 os_unfair_lock_t
*tp
= (os_unfair_lock_t
*)__p
;
353 os_unfair_lock_t ufl
= *tp
;
357 os_unfair_lock_assert_owner(ufl
);
358 os_unfair_lock_unlock(ufl
);
361 #else // __has_attribute(cleanup)
362 #define __os_cleanup_unsupported \
363 _Pragma("GCC error \"automatic cleanup not supported\"")
364 #define __os_free __os_cleanup_unsupported
365 #define __os_close __os_cleanup_unsupported
366 #define __os_fclose __os_cleanup_unsupported
367 #define __os_closedir __os_cleanup_unsupported
368 #define __os_close_mach_recv __os_cleanup_unsupported
369 #define __os_release_mach_send __os_cleanup_unsupported
370 #define __os_preserve_errno __os_cleanup_unsupported
371 #define __os_release __os_cleanup_unsupported
372 #define __os_cfrelease __os_cleanup_unsupported
373 #define __os_iorelease __os_cleanup_unsupported
374 #define __os_ioclose __os_cleanup_unsupported
375 #define __os_unfair_unlock __os_cleanup_unsupported
376 #endif // __has_attribute(cleanup)
380 #endif // __DARWIN_CLEANUP_H