this repo has no description
at fixPythonPipStalling 224 lines 5.4 kB view raw
1/* 2 * Copyright (c) 2012, 2013, 2015, 2016, 2018 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <TargetConditionals.h> 25#include <dispatch/dispatch.h> 26#include <dispatch/private.h> 27#include <os/log.h> 28#include <vproc.h> 29#include <vproc_priv.h> 30#include <xpc/xpc.h> 31 32#include "libSystemConfiguration_client.h" 33#include "libSystemConfiguration_internal.h" 34 35 36#pragma mark - 37#pragma mark libSC fork handlers 38 39 40static boolean_t _available = TRUE; 41 42// These functions are registered with libSystem to 43// handle pthread_atfork callbacks. 44 45void 46_libSC_info_fork_prepare() 47{ 48 return; 49} 50 51void 52_libSC_info_fork_parent() 53{ 54 return; 55} 56 57void 58_libSC_info_fork_child() 59{ 60 if (_dispatch_is_fork_of_multithreaded_parent()) { 61 _available = FALSE; 62 } 63 64 return; 65} 66 67 68#pragma mark - 69#pragma mark Support functions 70 71 72static void 73log_xpc_object(const char *msg, xpc_object_t obj) 74{ 75 char *desc; 76 77 desc = xpc_copy_description(obj); 78 os_log(OS_LOG_DEFAULT, "%s = %s", msg, desc); 79 free(desc); 80} 81 82 83__private_extern__ 84_Bool 85libSC_info_available() 86{ 87 return _available; 88} 89 90 91static void 92libSC_info_client_dealloc(libSC_info_client_t *client) 93{ 94 free(client->service_description); 95 free(client->service_name); 96 free(client); 97 return; 98} 99 100 101__private_extern__ 102libSC_info_client_t * 103libSC_info_client_create(dispatch_queue_t q, 104 const char *service_name, 105 const char *service_description) 106{ 107 xpc_connection_t c; 108 libSC_info_client_t *client; 109#if !TARGET_OS_SIMULATOR || TARGET_OS_IOSMAC 110 const uint64_t flags = XPC_CONNECTION_MACH_SERVICE_PRIVILEGED; 111#else // !TARGET_OS_SIMULATOR || TARGET_OS_IOSMAC 112 const uint64_t flags = 0; 113#endif // !TARGET_OS_SIMULATOR || TARGET_OS_IOSMAC 114 115 if (!_available) { 116 return NULL; 117 } 118 119 client = malloc(sizeof(libSC_info_client_t)); 120 client->active = TRUE; 121 client->service_description = strdup(service_description); 122 client->service_name = strdup(service_name); 123 124 c = xpc_connection_create_mach_service(service_name, q, flags); 125 126 xpc_connection_set_event_handler(c, ^(xpc_object_t xobj) { 127 xpc_type_t type; 128 129 type = xpc_get_type(xobj); 130 if (type == XPC_TYPE_DICTIONARY) { 131 os_log(OS_LOG_DEFAULT, "%s: unexpected message", client->service_name); 132 log_xpc_object(" dict = ", xobj); 133 } else if (type == XPC_TYPE_ERROR) { 134 if (xobj == XPC_ERROR_CONNECTION_INVALID) { 135 os_log(OS_LOG_DEFAULT, "%s: server not available", client->service_name); 136 client->active = FALSE; 137 } else if (xobj == XPC_ERROR_CONNECTION_INTERRUPTED) { 138 os_log_debug(OS_LOG_DEFAULT, "%s: server failed", client->service_name); 139 } else { 140 const char *desc; 141 142 desc = xpc_dictionary_get_string(xobj, XPC_ERROR_KEY_DESCRIPTION); 143 os_log_debug(OS_LOG_DEFAULT, 144 "%s: connection error: %d : %s", 145 client->service_name, 146 xpc_connection_get_pid(c), 147 desc); 148 } 149 } else { 150 os_log(OS_LOG_DEFAULT, 151 "%s: unknown event type : %p", 152 client->service_name, 153 type); 154 } 155 }); 156 157 client->connection = c; 158 159 xpc_connection_set_context(c, client); 160 xpc_connection_set_finalizer_f(c, (xpc_finalizer_t)libSC_info_client_dealloc); 161 162 xpc_connection_resume(c); 163 164 return client; 165} 166 167 168__private_extern__ 169void 170libSC_info_client_release(libSC_info_client_t *client) 171{ 172 xpc_release(client->connection); 173 return; 174} 175 176 177__private_extern__ 178xpc_object_t 179libSC_send_message_with_reply_sync(libSC_info_client_t *client, 180 xpc_object_t message) 181{ 182 xpc_object_t reply; 183 184 while (TRUE) { 185 // send request to the DNS configuration server 186 reply = xpc_connection_send_message_with_reply_sync(client->connection, message); 187 if (reply != NULL) { 188 xpc_type_t type; 189 190 type = xpc_get_type(reply); 191 if (type == XPC_TYPE_DICTIONARY) { 192 // reply available 193 break; 194 } 195 196 if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INTERRUPTED)) { 197 os_log_debug(OS_LOG_DEFAULT, 198 "%s server failure, retrying", 199 client->service_description); 200 // retry request 201 xpc_release(reply); 202 continue; 203 } 204 205 if ((type == XPC_TYPE_ERROR) && (reply == XPC_ERROR_CONNECTION_INVALID)) { 206 os_log(OS_LOG_DEFAULT, 207 "%s server not available", 208 client->service_description); 209 client->active = FALSE; 210 } else { 211 os_log(OS_LOG_DEFAULT, 212 "%s xpc_connection_send_message_with_reply_sync() with unexpected reply", 213 client->service_description); 214 log_xpc_object(" reply", reply); 215 } 216 217 xpc_release(reply); 218 reply = NULL; 219 break; 220 } 221 } 222 223 return reply; 224}