summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2015-01-22 01:46:02 +0100
committerGravatar Nikias Bassen2015-01-22 01:46:02 +0100
commita6ea54ec581470ed70c98c86b1619f9defca8b7e (patch)
tree2c30a554df06ee7c66395473b460c78f1591fee0 /tools
parent9c0e7ef16439b216f230341399275f15e9d0bfdf (diff)
downloadlibimobiledevice-a6ea54ec581470ed70c98c86b1619f9defca8b7e.tar.gz
libimobiledevice-a6ea54ec581470ed70c98c86b1619f9defca8b7e.tar.bz2
idevicedebugserverproxy: Properly handle server shutdown
Diffstat (limited to 'tools')
-rw-r--r--tools/idevicedebugserverproxy.c120
1 files changed, 75 insertions, 45 deletions
diff --git a/tools/idevicedebugserverproxy.c b/tools/idevicedebugserverproxy.c
index 2209abc..fc1ead9 100644
--- a/tools/idevicedebugserverproxy.c
+++ b/tools/idevicedebugserverproxy.c
@@ -38,33 +38,25 @@ static int debug_mode = 0;
38static int quit_flag = 0; 38static int quit_flag = 0;
39 39
40typedef struct { 40typedef struct {
41 int server_fd;
42 int client_fd; 41 int client_fd;
43 uint16_t local_port;
44 idevice_t device; 42 idevice_t device;
45 debugserver_client_t debugserver_client; 43 debugserver_client_t debugserver_client;
46 volatile int stop_ctod; 44 volatile int stop_ctod;
47 volatile int stop_dtoc; 45 volatile int stop_dtoc;
48} socket_info_t; 46} socket_info_t;
49 47
50static socket_info_t global_socket_info; 48struct thread_info {
49 thread_t th;
50 struct thread_info *next;
51};
52
53typedef struct thread_info thread_info_t;
54
51 55
52static void clean_exit(int sig) 56static void clean_exit(int sig)
53{ 57{
54 if (quit_flag == 0) 58 fprintf(stderr, "Exiting...\n");
55 fprintf(stderr, "Setting quit status. Cancel again to quit server.\n");
56 else
57 fprintf(stderr, "Exiting...\n");
58
59 quit_flag++; 59 quit_flag++;
60
61 /* shutdown server socket if we have to terminate to unblock the server loop */
62 if (quit_flag > 1) {
63 if (global_socket_info.server_fd > 0) {
64 socket_shutdown(global_socket_info.server_fd, SHUT_RDWR);
65 socket_close(global_socket_info.server_fd);
66 }
67 }
68} 60}
69 61
70static void print_usage(int argc, char **argv) 62static void print_usage(int argc, char **argv)
@@ -83,7 +75,7 @@ static void print_usage(int argc, char **argv)
83static void *thread_device_to_client(void *data) 75static void *thread_device_to_client(void *data)
84{ 76{
85 socket_info_t* socket_info = (socket_info_t*)data; 77 socket_info_t* socket_info = (socket_info_t*)data;
86 idevice_error_t res = IDEVICE_E_UNKNOWN_ERROR; 78 debugserver_error_t res = DEBUGSERVER_E_UNKNOWN_ERROR;
87 79
88 int recv_len; 80 int recv_len;
89 int sent; 81 int sent;
@@ -92,15 +84,14 @@ static void *thread_device_to_client(void *data)
92 debug("%s: started thread...\n", __func__); 84 debug("%s: started thread...\n", __func__);
93 85
94 debug("%s: client_fd = %d\n", __func__, socket_info->client_fd); 86 debug("%s: client_fd = %d\n", __func__, socket_info->client_fd);
95 debug("%s: server fd = %d\n", __func__, socket_info->server_fd);
96 87
97 while (!quit_flag && !socket_info->stop_dtoc && socket_info->client_fd > 0 && socket_info->server_fd > 0) { 88 while (!quit_flag && !socket_info->stop_dtoc && socket_info->client_fd > 0) {
98 debug("%s: receiving data from device...\n", __func__); 89 debug("%s: receiving data from device...\n", __func__);
99 90
100 res = debugserver_client_receive_with_timeout(socket_info->debugserver_client, buffer, sizeof(buffer), (uint32_t*)&recv_len, 5000); 91 res = debugserver_client_receive_with_timeout(socket_info->debugserver_client, buffer, sizeof(buffer), (uint32_t*)&recv_len, 5000);
101 92
102 if (recv_len <= 0) { 93 if (recv_len <= 0) {
103 if (recv_len == 0 && res == IDEVICE_E_SUCCESS) { 94 if (recv_len == 0 && res == DEBUGSERVER_E_SUCCESS) {
104 // try again 95 // try again
105 continue; 96 continue;
106 } else { 97 } else {
@@ -139,7 +130,7 @@ static void *thread_device_to_client(void *data)
139static void *thread_client_to_device(void *data) 130static void *thread_client_to_device(void *data)
140{ 131{
141 socket_info_t* socket_info = (socket_info_t*)data; 132 socket_info_t* socket_info = (socket_info_t*)data;
142 idevice_error_t res = IDEVICE_E_UNKNOWN_ERROR; 133 debugserver_error_t res = DEBUGSERVER_E_UNKNOWN_ERROR;
143 134
144 int recv_len; 135 int recv_len;
145 int sent; 136 int sent;
@@ -149,7 +140,6 @@ static void *thread_client_to_device(void *data)
149 debug("%s: started thread...\n", __func__); 140 debug("%s: started thread...\n", __func__);
150 141
151 debug("%s: client_fd = %d\n", __func__, socket_info->client_fd); 142 debug("%s: client_fd = %d\n", __func__, socket_info->client_fd);
152 debug("%s: server_fd = %d\n", __func__, socket_info->server_fd);
153 143
154 /* spawn server to client thread */ 144 /* spawn server to client thread */
155 socket_info->stop_dtoc = 0; 145 socket_info->stop_dtoc = 0;
@@ -157,7 +147,7 @@ static void *thread_client_to_device(void *data)
157 fprintf(stderr, "Failed to start device to client thread...\n"); 147 fprintf(stderr, "Failed to start device to client thread...\n");
158 } 148 }
159 149
160 while (!quit_flag && !socket_info->stop_ctod && socket_info->client_fd > 0 && socket_info->server_fd > 0) { 150 while (!quit_flag && !socket_info->stop_ctod && socket_info->client_fd > 0) {
161 debug("%s: receiving data from client...\n", __func__); 151 debug("%s: receiving data from client...\n", __func__);
162 152
163 /* attempt to read incoming data from client */ 153 /* attempt to read incoming data from client */
@@ -177,7 +167,7 @@ static void *thread_client_to_device(void *data)
177 debug("%s: sending data to device...\n", __func__); 167 debug("%s: sending data to device...\n", __func__);
178 res = debugserver_client_send(socket_info->debugserver_client, buffer, recv_len, (uint32_t*)&sent); 168 res = debugserver_client_send(socket_info->debugserver_client, buffer, recv_len, (uint32_t*)&sent);
179 169
180 if (sent < recv_len || res != IDEVICE_E_SUCCESS) { 170 if (sent < recv_len || res != DEBUGSERVER_E_SUCCESS) {
181 if (sent <= 0) { 171 if (sent <= 0) {
182 fprintf(stderr, "send failed: %s\n", strerror(errno)); 172 fprintf(stderr, "send failed: %s\n", strerror(errno));
183 break; 173 break;
@@ -245,18 +235,34 @@ static void* connection_handler(void* data)
245int main(int argc, char *argv[]) 235int main(int argc, char *argv[])
246{ 236{
247 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; 237 idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR;
248 thread_t th; 238 idevice_t device = NULL;
239 thread_info_t *thread_list = NULL;
249 const char* udid = NULL; 240 const char* udid = NULL;
250 uint16_t local_port = 0; 241 uint16_t local_port = 0;
242 int server_fd;
251 int result = EXIT_SUCCESS; 243 int result = EXIT_SUCCESS;
252 int i; 244 int i;
253 245
246#ifndef WIN32
247 struct sigaction sa;
248 struct sigaction si;
249 memset(&sa, '\0', sizeof(struct sigaction));
250 memset(&si, '\0', sizeof(struct sigaction));
251
252 sa.sa_handler = clean_exit;
253 sigemptyset(&sa.sa_mask);
254
255 si.sa_handler = SIG_IGN;
256 sigemptyset(&si.sa_mask);
257
258 sigaction(SIGINT, &sa, NULL);
259 sigaction(SIGTERM, &sa, NULL);
260 sigaction(SIGQUIT, &sa, NULL);
261 sigaction(SIGPIPE, &si, NULL);
262#else
254 /* bind signals */ 263 /* bind signals */
255 signal(SIGINT, clean_exit); 264 signal(SIGINT, clean_exit);
256 signal(SIGTERM, clean_exit); 265 signal(SIGTERM, clean_exit);
257#ifndef WIN32
258 signal(SIGQUIT, clean_exit);
259 signal(SIGPIPE, SIG_IGN);
260#endif 266#endif
261 267
262 /* parse cmdline arguments */ 268 /* parse cmdline arguments */
@@ -297,11 +303,8 @@ int main(int argc, char *argv[])
297 goto leave_cleanup; 303 goto leave_cleanup;
298 } 304 }
299 305
300 /* setup and create socket endpoint */
301 global_socket_info.local_port = local_port;
302
303 /* start services and connect to device */ 306 /* start services and connect to device */
304 ret = idevice_new(&global_socket_info.device, udid); 307 ret = idevice_new(&device, udid);
305 if (ret != IDEVICE_E_SUCCESS) { 308 if (ret != IDEVICE_E_SUCCESS) {
306 if (udid) { 309 if (udid) {
307 fprintf(stderr, "No device found with udid %s, is it plugged in?\n", udid); 310 fprintf(stderr, "No device found with udid %s, is it plugged in?\n", udid);
@@ -313,40 +316,67 @@ int main(int argc, char *argv[])
313 } 316 }
314 317
315 /* create local socket */ 318 /* create local socket */
316 global_socket_info.server_fd = socket_create(global_socket_info.local_port); 319 server_fd = socket_create(local_port);
317 if (global_socket_info.server_fd < 0) { 320 if (server_fd < 0) {
318 fprintf(stderr, "Could not create socket\n"); 321 fprintf(stderr, "Could not create socket\n");
319 result = EXIT_FAILURE; 322 result = EXIT_FAILURE;
320 goto leave_cleanup; 323 goto leave_cleanup;
321 } 324 }
322 325
323 while (!quit_flag) { 326 while (!quit_flag) {
324 debug("%s: Waiting for connection on local port %d\n", __func__, global_socket_info.local_port); 327 debug("%s: Waiting for connection on local port %d\n", __func__, local_port);
325 328
326 /* wait for client */ 329 /* wait for client */
327 global_socket_info.client_fd = socket_accept(global_socket_info.server_fd, global_socket_info.local_port); 330 int client_fd = socket_accept(server_fd, local_port);
328 if (global_socket_info.client_fd < 0) { 331 if (client_fd < 0) {
329 continue; 332 continue;
330 } 333 }
331 334
332 debug("%s: Handling new client connection...\n", __func__); 335 debug("%s: Handling new client connection...\n", __func__);
333 336
334 if (thread_new(&th, connection_handler, (void*)&global_socket_info) != 0) { 337 thread_info_t *el = (thread_info_t*)malloc(sizeof(thread_info_t));
338 if (!el) {
339 fprintf(stderr, "Out of memory\n");
340 exit(EXIT_FAILURE);
341 }
342 el->next = NULL;
343
344 if (thread_list) {
345 thread_list->next = el;
346 } else {
347 thread_list = el;
348 }
349
350 socket_info_t *sinfo = (socket_info_t*)malloc(sizeof(socket_info_t));
351 if (!sinfo) {
352 fprintf(stderr, "Out of memory\n");
353 exit(EXIT_FAILURE);
354 }
355 sinfo->client_fd = client_fd;
356 sinfo->device = device;
357
358 if (thread_new(&(el->th), connection_handler, (void*)sinfo) != 0) {
335 fprintf(stderr, "Could not start connection handler.\n"); 359 fprintf(stderr, "Could not start connection handler.\n");
336 socket_shutdown(global_socket_info.server_fd, SHUT_RDWR); 360 socket_shutdown(server_fd, SHUT_RDWR);
337 socket_close(global_socket_info.server_fd); 361 socket_close(server_fd);
338 continue; 362 continue;
339 } 363 }
340
341 /* we do not need it anymore */
342 thread_free(th);
343 } 364 }
344 365
345 debug("%s: Shutting down debugserver proxy...\n", __func__); 366 debug("%s: Shutting down debugserver proxy...\n", __func__);
346 367
368 /* join and clean up threads */
369 while (thread_list) {
370 thread_info_t *el = thread_list;
371 thread_join(el->th);
372 thread_free(el->th);
373 thread_list = el->next;
374 free(el);
375 }
376
347leave_cleanup: 377leave_cleanup:
348 if (global_socket_info.device) { 378 if (device) {
349 idevice_free(global_socket_info.device); 379 idevice_free(device);
350 } 380 }
351 381
352 return result; 382 return result;