diff options
| author | 2009-02-27 03:00:27 +0100 | |
|---|---|---|
| committer | 2009-02-27 03:00:27 +0100 | |
| commit | 365b6c9b208e483af751a43a9ccc8885553859ee (patch) | |
| tree | 71d50cc8ae2ca011629c7d6e0a81d4b1dd17149b /main.c | |
| parent | f909955d615df615d5c48c2e5829d5e861bcfb2d (diff) | |
| download | usbmuxd-365b6c9b208e483af751a43a9ccc8885553859ee.tar.gz usbmuxd-365b6c9b208e483af751a43a9ccc8885553859ee.tar.bz2 | |
1) Now, every device is only handled by one thread for bulk usb reading
instead of one thread for each connection to the same device.
2) Removed usbmuxd_accept_thread and moved code into main() directly.
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 183 |
1 files changed, 110 insertions, 73 deletions
| @@ -49,11 +49,13 @@ struct device_use_info { | |||
| 49 | uint32_t device_id; | 49 | uint32_t device_id; |
| 50 | iphone_device_t phone; | 50 | iphone_device_t phone; |
| 51 | int use_count; | 51 | int use_count; |
| 52 | pthread_t bulk_reader; | ||
| 53 | pthread_mutex_t mutex; | ||
| 52 | /* mutex for mutual exclusion of calling the iphone_mux_send function | 54 | /* mutex for mutual exclusion of calling the iphone_mux_send function |
| 53 | * TODO: I don't know if we need really need this? */ | 55 | * TODO: I don't know if we need really need this? */ |
| 54 | pthread_mutex_t writer_mutex; | 56 | pthread_mutex_t writer_mutex; |
| 55 | /* mutex to keep the reader threads from reading partial packages */ | 57 | /* mutex to keep the reader threads from reading partial packages */ |
| 56 | pthread_mutex_t reader_mutex; | 58 | //pthread_mutex_t reader_mutex; |
| 57 | }; | 59 | }; |
| 58 | 60 | ||
| 59 | struct client_data { | 61 | struct client_data { |
| @@ -66,6 +68,7 @@ struct client_data { | |||
| 66 | int reader_quit; | 68 | int reader_quit; |
| 67 | int reader_dead; | 69 | int reader_dead; |
| 68 | int handler_dead; | 70 | int handler_dead; |
| 71 | int connected; | ||
| 69 | iphone_umux_client_t muxclient; | 72 | iphone_umux_client_t muxclient; |
| 70 | struct device_use_info *duinfo; | 73 | struct device_use_info *duinfo; |
| 71 | }; | 74 | }; |
| @@ -269,9 +272,9 @@ static int usbmuxd_handleConnectResult(struct client_data *cdata) | |||
| 269 | } | 272 | } |
| 270 | } else { | 273 | } else { |
| 271 | result = 0; | 274 | result = 0; |
| 272 | pthread_mutex_lock(&cdata->duinfo->reader_mutex); | 275 | //pthread_mutex_lock(&cdata->duinfo->reader_mutex); |
| 273 | err = iphone_mux_recv_timeout(cdata->muxclient, buffer, maxlen, &rlen, DEFAULT_TIMEOUT); | 276 | err = iphone_mux_recv_timeout(cdata->muxclient, buffer, maxlen, &rlen, DEFAULT_TIMEOUT); |
| 274 | pthread_mutex_unlock(&cdata->duinfo->reader_mutex); | 277 | //pthread_mutex_unlock(&cdata->duinfo->reader_mutex); |
| 275 | if (err != 0) { | 278 | if (err != 0) { |
| 276 | fprintf(stderr, "%s: encountered USB read error: %d\n", __func__, err); | 279 | fprintf(stderr, "%s: encountered USB read error: %d\n", __func__, err); |
| 277 | usbmuxd_send_result(cdata->socket, cdata->tag, -err); | 280 | usbmuxd_send_result(cdata->socket, cdata->tag, -err); |
| @@ -404,6 +407,46 @@ leave: | |||
| 404 | } | 407 | } |
| 405 | 408 | ||
| 406 | /** | 409 | /** |
| 410 | * Thread performing usb_bulk_read from the connected device. | ||
| 411 | * One thread per device. Lives as long as the device is in use. | ||
| 412 | */ | ||
| 413 | static void *usbmuxd_bulk_reader_thread(void *arg) | ||
| 414 | { | ||
| 415 | struct device_use_info *cur_dev; | ||
| 416 | |||
| 417 | if (!arg) { | ||
| 418 | fprintf(stderr, "%s: Invalid client_data provided\n", __func__); | ||
| 419 | return NULL; | ||
| 420 | } | ||
| 421 | |||
| 422 | cur_dev = (struct device_use_info*)arg; | ||
| 423 | |||
| 424 | printf("%s: started\n", __func__); | ||
| 425 | |||
| 426 | while (!quit_flag && cur_dev) { | ||
| 427 | |||
| 428 | pthread_mutex_lock(&cur_dev->mutex); | ||
| 429 | if (cur_dev->use_count <= 0) { | ||
| 430 | pthread_mutex_unlock(&cur_dev->mutex); | ||
| 431 | break; | ||
| 432 | } | ||
| 433 | pthread_mutex_unlock(&cur_dev->mutex); | ||
| 434 | |||
| 435 | //pthread_mutex_lock(&cur_dev->reader_mutex); | ||
| 436 | iphone_mux_pullbulk(cur_dev->phone); | ||
| 437 | //err = iphone_mux_get_error(cdata->muxclient); | ||
| 438 | //pthread_mutex_unlock(&cur_dev->reader_mutex); | ||
| 439 | //if (err != IPHONE_E_SUCCESS) { | ||
| 440 | // break; | ||
| 441 | //} | ||
| 442 | } | ||
| 443 | |||
| 444 | printf("%s: terminated\n", __func__); | ||
| 445 | |||
| 446 | return NULL; | ||
| 447 | } | ||
| 448 | |||
| 449 | /** | ||
| 407 | * This thread is started when a new connection is accepted. | 450 | * This thread is started when a new connection is accepted. |
| 408 | * It performs the handshake, then waits for the connect packet and | 451 | * It performs the handshake, then waits for the connect packet and |
| 409 | * on success it starts the usbmuxd_client_handler thread. | 452 | * on success it starts the usbmuxd_client_handler thread. |
| @@ -422,8 +465,8 @@ static void *usbmuxd_client_init_thread(void *arg) | |||
| 422 | int found = 0; | 465 | int found = 0; |
| 423 | int res; | 466 | int res; |
| 424 | int i; | 467 | int i; |
| 425 | int sent_result; | 468 | // int sent_result; |
| 426 | iphone_error_t err; | 469 | // iphone_error_t err; |
| 427 | 470 | ||
| 428 | iphone_device_t phone; | 471 | iphone_device_t phone; |
| 429 | struct device_use_info *cur_dev = NULL; | 472 | struct device_use_info *cur_dev = NULL; |
| @@ -549,10 +592,12 @@ static void *usbmuxd_client_init_thread(void *arg) | |||
| 549 | cur_dev->use_count = 1; | 592 | cur_dev->use_count = 1; |
| 550 | cur_dev->device_id = c_req.device_id; | 593 | cur_dev->device_id = c_req.device_id; |
| 551 | cur_dev->phone = phone; | 594 | cur_dev->phone = phone; |
| 552 | pthread_mutex_init(&cur_dev->reader_mutex, NULL); | 595 | pthread_mutex_init(&cur_dev->mutex, NULL); |
| 596 | //pthread_mutex_init(&cur_dev->reader_mutex, NULL); | ||
| 553 | pthread_mutex_init(&cur_dev->writer_mutex, NULL); | 597 | pthread_mutex_init(&cur_dev->writer_mutex, NULL); |
| 554 | 598 | ||
| 555 | fprintf(stdout, "%s: device_use_count = %d\n", __func__, device_use_count); | 599 | fprintf(stdout, "%s: device_use_count = %d\n", __func__, device_use_count); |
| 600 | pthread_create(&cur_dev->bulk_reader, NULL, usbmuxd_bulk_reader_thread, cur_dev); | ||
| 556 | 601 | ||
| 557 | pthread_mutex_lock(&usbmux_mutex); | 602 | pthread_mutex_lock(&usbmux_mutex); |
| 558 | device_use_list = (struct device_use_info**)realloc(device_use_list, sizeof(struct device_use_info*) * (device_use_count+1)); | 603 | device_use_list = (struct device_use_info**)realloc(device_use_list, sizeof(struct device_use_info*) * (device_use_count+1)); |
| @@ -586,11 +631,12 @@ static void *usbmuxd_client_init_thread(void *arg) | |||
| 586 | goto leave; | 631 | goto leave; |
| 587 | } | 632 | } |
| 588 | 633 | ||
| 589 | sent_result = 0; | 634 | //sent_result = 0; |
| 590 | 635 | ||
| 591 | // TODO: wait for connect result? | 636 | // TODO: wait for connect result? |
| 592 | // if connect failed, don't run this loop: | 637 | // if connect failed, don't run this loop: |
| 593 | 638 | ||
| 639 | /* | ||
| 594 | // start reading data from the connected device | 640 | // start reading data from the connected device |
| 595 | while (!quit_flag && !cdata->handler_dead) { | 641 | while (!quit_flag && !cdata->handler_dead) { |
| 596 | pthread_mutex_lock(&cur_dev->reader_mutex); | 642 | pthread_mutex_lock(&cur_dev->reader_mutex); |
| @@ -606,14 +652,16 @@ static void *usbmuxd_client_init_thread(void *arg) | |||
| 606 | //fprintf(stderr, "Sending error message %d tag %d\n", err, c_req.header.tag); | 652 | //fprintf(stderr, "Sending error message %d tag %d\n", err, c_req.header.tag); |
| 607 | err = iphone_mux_get_error(cdata->muxclient); | 653 | err = iphone_mux_get_error(cdata->muxclient); |
| 608 | //usbmuxd_send_result(cdata->socket, c_req.header.tag, err); | 654 | //usbmuxd_send_result(cdata->socket, c_req.header.tag, err); |
| 609 | } | 655 | }*/ |
| 610 | 656 | ||
| 611 | fprintf(stdout, "%s: terminating\n", __func__); | 657 | //fprintf(stdout, "%s: terminating\n", __func__); |
| 612 | 658 | ||
| 613 | // wait for handler thread to finish its work | 659 | // wait for handler thread to finish its work |
| 614 | if (cdata->handler != 0) { | 660 | if (cdata->handler != 0) { |
| 615 | pthread_join(cdata->handler, NULL); | 661 | pthread_join(cdata->handler, NULL); |
| 616 | } | 662 | } |
| 663 | |||
| 664 | fprintf(stdout, "%s: closing connection\n", __func__); | ||
| 617 | 665 | ||
| 618 | // time to clean up | 666 | // time to clean up |
| 619 | if (cdata && cdata->muxclient) { // should be non-NULL | 667 | if (cdata && cdata->muxclient) { // should be non-NULL |
| @@ -621,16 +669,25 @@ static void *usbmuxd_client_init_thread(void *arg) | |||
| 621 | } | 669 | } |
| 622 | 670 | ||
| 623 | leave: | 671 | leave: |
| 672 | fprintf(stdout, "%s: terminating\n", __func__); | ||
| 673 | |||
| 624 | // this has to be freed only if it's not in use anymore as it closes | 674 | // this has to be freed only if it's not in use anymore as it closes |
| 625 | // the USB connection | 675 | // the USB connection |
| 626 | if (cur_dev) { | 676 | if (cur_dev) { |
| 677 | pthread_mutex_lock(&cur_dev->mutex); | ||
| 627 | if (cur_dev->use_count > 1) { | 678 | if (cur_dev->use_count > 1) { |
| 679 | printf("%s: decreasing device use count\n", __func__); | ||
| 628 | cur_dev->use_count--; | 680 | cur_dev->use_count--; |
| 681 | pthread_mutex_unlock(&cur_dev->mutex); | ||
| 629 | } else { | 682 | } else { |
| 630 | iphone_free_device(cur_dev->phone); | 683 | printf("%s: last client disconnected, cleaning up\n", __func__); |
| 631 | cur_dev->use_count = 0; | 684 | cur_dev->use_count = 0; |
| 632 | pthread_mutex_destroy(&cur_dev->reader_mutex); | 685 | pthread_mutex_unlock(&cur_dev->mutex); |
| 686 | pthread_join(cur_dev->bulk_reader, NULL); | ||
| 687 | iphone_free_device(cur_dev->phone); | ||
| 688 | //pthread_mutex_destroy(&cur_dev->reader_mutex); | ||
| 633 | pthread_mutex_destroy(&cur_dev->writer_mutex); | 689 | pthread_mutex_destroy(&cur_dev->writer_mutex); |
| 690 | pthread_mutex_destroy(&cur_dev->mutex); | ||
| 634 | free(cur_dev); | 691 | free(cur_dev); |
| 635 | cur_dev = NULL; | 692 | cur_dev = NULL; |
| 636 | pthread_mutex_lock(&usbmux_mutex); | 693 | pthread_mutex_lock(&usbmux_mutex); |
| @@ -683,30 +740,54 @@ static void clean_exit(int sig) | |||
| 683 | } | 740 | } |
| 684 | 741 | ||
| 685 | /** | 742 | /** |
| 686 | * thread function that performs accept() and starts the required child | 743 | * main function. Initializes all stuff and then loops waiting in accept. |
| 687 | * threads to perform the rest of the communication stuff. | ||
| 688 | */ | 744 | */ |
| 689 | static void *usbmuxd_accept_thread(void *arg) | 745 | int main(int argc, char **argv) |
| 690 | { | 746 | { |
| 747 | int foreground = 1; | ||
| 691 | struct sockaddr_un c_addr; | 748 | struct sockaddr_un c_addr; |
| 692 | socklen_t len = sizeof(struct sockaddr_un); | 749 | socklen_t len = sizeof(struct sockaddr_un); |
| 693 | struct client_data *cdata; | 750 | struct client_data *cdata = NULL; |
| 694 | struct client_data **children = NULL; | 751 | struct client_data **children = NULL; |
| 695 | int children_capacity = DEFAULT_CHILDREN_CAPACITY; | 752 | int children_capacity = DEFAULT_CHILDREN_CAPACITY; |
| 696 | int i = 0; | 753 | int i = 0; |
| 697 | int result = 0; | 754 | int result = 0; |
| 698 | int cnt; | 755 | int cnt = 0; |
| 756 | |||
| 757 | fprintf(stdout, "usbmuxd: starting\n"); | ||
| 758 | |||
| 759 | // TODO: Parameter checking. | ||
| 760 | |||
| 761 | fsock = create_unix_socket(USBMUXD_SOCKET_FILE); | ||
| 762 | if (fsock < 0) { | ||
| 763 | fprintf(stderr, "Could not create socket, exiting\n"); | ||
| 764 | return -1; | ||
| 765 | } | ||
| 766 | |||
| 767 | chmod(USBMUXD_SOCKET_FILE, 0666); | ||
| 768 | |||
| 769 | if (!foreground) { | ||
| 770 | if (daemonize() < 0) { | ||
| 771 | exit(EXIT_FAILURE); | ||
| 772 | } | ||
| 773 | } | ||
| 774 | |||
| 775 | // signal(SIGHUP, reload_conf); // none yet | ||
| 776 | signal(SIGINT, clean_exit); | ||
| 777 | signal(SIGQUIT, clean_exit); | ||
| 778 | signal(SIGTERM, clean_exit); | ||
| 779 | signal(SIGPIPE, SIG_IGN); | ||
| 699 | 780 | ||
| 700 | // Reserve space for 10 clients which should be enough. If not, the | 781 | // Reserve space for 10 clients which should be enough. If not, the |
| 701 | // buffer gets enlarged later. | 782 | // buffer gets enlarged later. |
| 702 | children = (struct client_data**)malloc(sizeof(struct client_data*) * children_capacity); | 783 | children = (struct client_data**)malloc(sizeof(struct client_data*) * children_capacity); |
| 703 | if (!children) { | 784 | if (!children) { |
| 704 | fprintf(stderr, "%s: Out of memory when allocating memory for child threads. Terminating.\n", __func__); | 785 | fprintf(stderr, "usbmuxd: Out of memory when allocating memory for child threads. Terminating.\n"); |
| 705 | exit(EXIT_FAILURE); | 786 | exit(EXIT_FAILURE); |
| 706 | } | 787 | } |
| 707 | memset(children, 0, sizeof(struct client_data*) * children_capacity); | 788 | memset(children, 0, sizeof(struct client_data*) * children_capacity); |
| 708 | 789 | ||
| 709 | fprintf(stdout, "%s: waiting for connection\n", __func__); | 790 | fprintf(stdout, "usbmuxd: waiting for connection\n"); |
| 710 | while (!quit_flag) { | 791 | while (!quit_flag) { |
| 711 | // Check the file descriptor before accepting a connection. | 792 | // Check the file descriptor before accepting a connection. |
| 712 | // If no connection attempt is made, just repeat... | 793 | // If no connection attempt is made, just repeat... |
| @@ -718,7 +799,7 @@ static void *usbmuxd_accept_thread(void *arg) | |||
| 718 | if (children[i]) { | 799 | if (children[i]) { |
| 719 | if (children[i]->dead != 0) { | 800 | if (children[i]->dead != 0) { |
| 720 | pthread_join(children[i]->thread, NULL); | 801 | pthread_join(children[i]->thread, NULL); |
| 721 | fprintf(stdout, "%s: reclaimed client thread (fd=%d)\n", __func__, children[i]->socket); | 802 | fprintf(stdout, "usbmuxd: reclaimed client thread (fd=%d)\n", children[i]->socket); |
| 722 | free(children[i]); | 803 | free(children[i]); |
| 723 | children[i] = NULL; | 804 | children[i] = NULL; |
| 724 | cnt++; | 805 | cnt++; |
| @@ -737,7 +818,7 @@ static void *usbmuxd_accept_thread(void *arg) | |||
| 737 | } | 818 | } |
| 738 | continue; | 819 | continue; |
| 739 | } else { | 820 | } else { |
| 740 | fprintf(stderr, "select error: %s\n", strerror(errno)); | 821 | fprintf(stderr, "usbmuxd: select error: %s\n", strerror(errno)); |
| 741 | continue; | 822 | continue; |
| 742 | } | 823 | } |
| 743 | } | 824 | } |
| @@ -746,7 +827,7 @@ static void *usbmuxd_accept_thread(void *arg) | |||
| 746 | memset(cdata, 0, sizeof(struct client_data)); | 827 | memset(cdata, 0, sizeof(struct client_data)); |
| 747 | if (!cdata) { | 828 | if (!cdata) { |
| 748 | quit_flag = 1; | 829 | quit_flag = 1; |
| 749 | fprintf(stderr, "%s: Error: Out of memory! Terminating.\n", __func__); | 830 | fprintf(stderr, "usbmuxd: Error: Out of memory! Terminating.\n"); |
| 750 | break; | 831 | break; |
| 751 | } | 832 | } |
| 752 | 833 | ||
| @@ -756,12 +837,12 @@ static void *usbmuxd_accept_thread(void *arg) | |||
| 756 | if (errno == EINTR) { | 837 | if (errno == EINTR) { |
| 757 | continue; | 838 | continue; |
| 758 | } else { | 839 | } else { |
| 759 | fprintf(stderr, "%s: Error in accept: %s\n", __func__, strerror(errno)); | 840 | fprintf(stderr, "usbmuxd: Error in accept: %s\n", strerror(errno)); |
| 760 | continue; | 841 | continue; |
| 761 | } | 842 | } |
| 762 | } | 843 | } |
| 763 | 844 | ||
| 764 | fprintf(stdout, "%s: new client connected (fd=%d)\n", __func__, cdata->socket); | 845 | fprintf(stdout, "usbmuxd: new client connected (fd=%d)\n", cdata->socket); |
| 765 | 846 | ||
| 766 | // create client thread: | 847 | // create client thread: |
| 767 | if (pthread_create(&cdata->thread, NULL, usbmuxd_client_init_thread, cdata) == 0) { | 848 | if (pthread_create(&cdata->thread, NULL, usbmuxd_client_init_thread, cdata) == 0) { |
| @@ -773,22 +854,22 @@ static void *usbmuxd_accept_thread(void *arg) | |||
| 773 | children_capacity++; | 854 | children_capacity++; |
| 774 | children = realloc(children, sizeof(struct client_data*) * children_capacity); | 855 | children = realloc(children, sizeof(struct client_data*) * children_capacity); |
| 775 | if (!children) { | 856 | if (!children) { |
| 776 | fprintf(stderr, "%s: Out of memory when enlarging child thread buffer\n", __func__); | 857 | fprintf(stderr, "usbmuxd: Out of memory when enlarging child thread buffer\n"); |
| 777 | } | 858 | } |
| 778 | } | 859 | } |
| 779 | children[i] = cdata; | 860 | children[i] = cdata; |
| 780 | } else { | 861 | } else { |
| 781 | fprintf(stderr, "%s: Failed to create client_init_thread.\n", __func__); | 862 | fprintf(stderr, "usbmuxd: Failed to create client_init_thread.\n"); |
| 782 | close(cdata->socket); | 863 | close(cdata->socket); |
| 783 | free(cdata); | 864 | free(cdata); |
| 784 | cdata = NULL; | 865 | cdata = NULL; |
| 785 | } | 866 | } |
| 786 | } | 867 | } |
| 787 | 868 | ||
| 788 | fprintf(stdout, "%s: terminating\n", __func__); | 869 | fprintf(stdout, "usbmuxd: terminating\n"); |
| 789 | 870 | ||
| 790 | // preparing for shutdown: wait for child threads to terminate (if any) | 871 | // preparing for shutdown: wait for child threads to terminate (if any) |
| 791 | fprintf(stdout, "%s: waiting for child threads to terminate...\n", __func__); | 872 | fprintf(stdout, "usbmuxd: waiting for child threads to terminate...\n"); |
| 792 | for (i = 0; i < children_capacity; i++) { | 873 | for (i = 0; i < children_capacity; i++) { |
| 793 | if (children[i] != NULL) { | 874 | if (children[i] != NULL) { |
| 794 | pthread_join(children[i]->thread, NULL); | 875 | pthread_join(children[i]->thread, NULL); |
| @@ -800,59 +881,15 @@ static void *usbmuxd_accept_thread(void *arg) | |||
| 800 | free(children); | 881 | free(children); |
| 801 | children = NULL; | 882 | children = NULL; |
| 802 | 883 | ||
| 803 | fprintf(stdout, "%s: terminated.\n", __func__); | ||
| 804 | |||
| 805 | return NULL; | ||
| 806 | } | ||
| 807 | 884 | ||
| 808 | /** | ||
| 809 | * main function. | ||
| 810 | */ | ||
| 811 | int main(int argc, char **argv) | ||
| 812 | { | ||
| 813 | int foreground = 1; | ||
| 814 | pthread_t acceptor; | ||
| 815 | |||
| 816 | fprintf(stdout, "usbmuxd: starting\n"); | ||
| 817 | |||
| 818 | // TODO: Parameter checking. | ||
| 819 | |||
| 820 | fsock = create_unix_socket(USBMUXD_SOCKET_FILE); | ||
| 821 | if (fsock < 0) { | ||
| 822 | fprintf(stderr, "Could not create socket, exiting\n"); | ||
| 823 | return -1; | ||
| 824 | } | ||
| 825 | |||
| 826 | chmod(USBMUXD_SOCKET_FILE, 0666); | ||
| 827 | |||
| 828 | if (!foreground) { | ||
| 829 | if (daemonize() < 0) { | ||
| 830 | exit(EXIT_FAILURE); | ||
| 831 | } | ||
| 832 | } | ||
| 833 | |||
| 834 | // signal(SIGHUP, reload_conf); // none yet | ||
| 835 | signal(SIGINT, clean_exit); | ||
| 836 | signal(SIGQUIT, clean_exit); | ||
| 837 | signal(SIGTERM, clean_exit); | ||
| 838 | signal(SIGPIPE, SIG_IGN); | ||
| 839 | |||
| 840 | if (pthread_create(&acceptor, NULL, usbmuxd_accept_thread, NULL) != 0) { | ||
| 841 | fprintf(stderr, "Failed to create server thread.\n"); | ||
| 842 | close(fsock); | ||
| 843 | return -1; | ||
| 844 | } | ||
| 845 | |||
| 846 | // Relax here. Just wait for the accept thread to terminate. | ||
| 847 | pthread_join(acceptor, NULL); | ||
| 848 | |||
| 849 | fprintf(stdout, "usbmuxd: terminating\n"); | ||
| 850 | if (fsock >= 0) { | 885 | if (fsock >= 0) { |
| 851 | close(fsock); | 886 | close(fsock); |
| 852 | } | 887 | } |
| 853 | 888 | ||
| 854 | unlink(USBMUXD_SOCKET_FILE); | 889 | unlink(USBMUXD_SOCKET_FILE); |
| 855 | 890 | ||
| 891 | fprintf(stdout, "usbmuxd: terminated\n"); | ||
| 892 | |||
| 856 | return 0; | 893 | return 0; |
| 857 | } | 894 | } |
| 858 | 895 | ||
