Merge pull request #68 from senthilmanick/master

Fixed the hang when the device is locked.

When the device is locked, we get empty packets in the server.
Now fixed by closing both the lldb and server sockets.
Also after safequit, we need to detach to make the "justlaunch" option to be less error prone.

Multiple bug fixes: 
1. When multiple devices are connected, the detect was not listing all the devices ios-deploy -c -t 1
2. Fixes for issue #75 - non-interactive mode broken lldb and ios-deploy may still be running ios-deploy -b ... -d -I -L
3. Fixes for issue #60 - -L option not working properly ios-deploy will not quit or sometimes hang
4. When multiple devices are connected, cannot use -i option to specify the device ios-deploy -b ... -i -d -I -L
5. Allow timeout when downloading
This commit is contained in:
Shazron Abdullah 2014-11-12 16:11:52 -08:00
commit 7ca72695b6

View File

@ -16,7 +16,7 @@
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include "MobileDevice.h" #include "MobileDevice.h"
#define APP_VERSION "1.2.2" #define APP_VERSION "1.3.0"
#define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-"
#define LLDB_SHELL "lldb -s " PREP_CMDS_PATH #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH
/* /*
@ -110,8 +110,6 @@ def safequit_command(debugger, command, result, internal_dict):\n\
state = process.GetStateFromEvent(event)\n\ state = process.GetStateFromEvent(event)\n\
else:\n\ else:\n\
state = lldb.eStateInvalid\n\ state = lldb.eStateInvalid\n\
print('\\nin process\\n')\n\
print(state)\n\
process.Detach()\n\ process.Detach()\n\
sys.exit(0)\n\ sys.exit(0)\n\
\n\ \n\
@ -833,18 +831,28 @@ CFSocketRef lldb_socket;
CFWriteStreamRef serverWriteStream = NULL; CFWriteStreamRef serverWriteStream = NULL;
CFWriteStreamRef lldbWriteStream = NULL; CFWriteStreamRef lldbWriteStream = NULL;
int kill_ptree(pid_t root, int signum);
void void
server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info) server_callback (CFSocketRef s, CFSocketCallBackType callbackType, CFDataRef address, const void *data, void *info)
{ {
int res; int res;
//printf("server: %s\n", CFDataGetBytePtr (data));
if (CFDataGetLength (data) == 0) { if (CFDataGetLength (data) == 0) {
// FIXME: Close the socket // FIXME: Close the socket
//shutdown (CFSocketGetNative (lldb_socket), SHUT_RDWR); //shutdown (CFSocketGetNative (lldb_socket), SHUT_RDWR);
//close (CFSocketGetNative (lldb_socket)); //close (CFSocketGetNative (lldb_socket));
CFSocketInvalidate(lldb_socket); CFSocketInvalidate(lldb_socket);
CFSocketInvalidate(server_socket); CFSocketInvalidate(server_socket);
int mypid = getpid();
assert((child != 0) && (child != mypid)); //child should not be here
if ((parent != 0) && (parent == mypid) && (child != 0))
{
if (verbose)
{
printf("Got an empty packet hence killing child (%d) tree\n", child);
}
kill_ptree(child, SIGHUP);
}
exit(exitcode_error); exit(exitcode_error);
return; return;
} }
@ -965,7 +973,6 @@ void lldb_finished_handler(int signum)
} }
void bring_process_to_foreground() { void bring_process_to_foreground() {
printf("Bringing process to foreground\n");
if (setpgid(0, 0) == -1) if (setpgid(0, 0) == -1)
perror("setpgid failed"); perror("setpgid failed");
@ -976,7 +983,6 @@ void bring_process_to_foreground() {
} }
void setup_dummy_pipe_on_stdin(int pfd[2]) { void setup_dummy_pipe_on_stdin(int pfd[2]) {
printf("Setting up dummy pipe\n");
if (pipe(pfd) == -1) if (pipe(pfd) == -1)
perror("pipe failed"); perror("pipe failed");
if (dup2(pfd[0], STDIN_FILENO) == -1) if (dup2(pfd[0], STDIN_FILENO) == -1)
@ -1064,60 +1070,8 @@ void launch_debugger(AMDeviceRef device, CFURLRef url) {
} }
} }
#define USE_SYSTEM 1
void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) { void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) {
setup_lldb(device,url); setup_lldb(device,url);
#ifdef USE_SYSTEM
#define PARENT_READ pfd[0]
#define CHILD_WRITE pfd[1]
#define CHILD_READ pfd[0]
#define PARENT_WRITE pfd[1]
int pfd[2] = {-1, -1};
if (pipe(pfd) == -1)
perror("Pipe failed");
int pid = fork();
if (pid == 0) {
signal(SIGHUP, SIG_DFL);
signal(SIGLLDB, SIG_DFL);
child = getpid();
//close(pfd[1]);
if (dup2(pfd[0],STDIN_FILENO) == -1)
perror("dup2 failed");
char lldb_shell[400];
sprintf(lldb_shell, LLDB_SHELL);
if(device_id != NULL)
strcat(lldb_shell, device_id);
int status = system(lldb_shell); // launch lldb
if (status == -1)
perror("failed launching lldb");
printf("Done launching\n");
close(pfd[0]);
// Notify parent we're exiting
kill(parent, SIGLLDB);
// Pass lldb exit code
_exit(WEXITSTATUS(status));
} else if (pid > 0) {
child = pid;
//char ch;
//while(read(pfd[1],&ch,1))
// printf("[%c]",ch);
} else {
perror("fork failed");
exit(exitcode_error);
}
#endif
#ifdef USE_EXEC
#define PARENT_READ pfd[0]
#define CHILD_WRITE pfd[1]
#define CHILD_READ pfd[0]
#define PARENT_WRITE pfd[1]
int pfd[2] = {-1, -1}; int pfd[2] = {-1, -1};
if (pipe(pfd) == -1) if (pipe(pfd) == -1)
perror("Pipe failed"); perror("Pipe failed");
@ -1129,84 +1083,6 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) {
if (dup2(pfd[0],STDIN_FILENO) == -1) if (dup2(pfd[0],STDIN_FILENO) == -1)
perror("dup2 failed"); perror("dup2 failed");
if (dup2(pfd[1],STDOUT_FILENO) == -1)
perror("dup2 failed for out");
char lldb_shell[400];
sprintf(lldb_shell, PREP_CMDS_PATH);
if(device_id != NULL)
strcat(lldb_shell, device_id);
char *path[4];
path[0] = "lldb";
path[1] = "-s";
path[2] = lldb_shell;
path[3] = NULL;
/* path[0] = "echo";
path[1] = "hello";
path[2] = NULL;*/
int status = execvp(path[0],path);
if (status == -1)
perror("failed launching lldb");
close(pfd[0]);
close(pfd[1]);
// Notify parent we're exiting
kill(parent, SIGLLDB);
// Pass lldb exit code
_exit(WEXITSTATUS(status));
} else if (pid > 0) {
child = pid;
char ch;
bool eof = false;
while (!eof)
{
int ret = read(pfd[0],&ch,1);
printf("%c",ch);
}
printf("Done");
} else {
perror("fork failed");
exit(exitcode_error);
}
#endif
#ifdef USE_PIPE
printf("--------USING PIPE------\n");
char lldb_shell[400];
sprintf(lldb_shell, LLDB_SHELL);
if(device_id != NULL)
strcat(lldb_shell, device_id);
FILE *lldb = popen(lldb_shell, "rw");
if (lldb == NULL)
perror("failed popen");
while (!feof(lldb))
{
char buffer[128];
char *ret = fgets(buffer, 128, lldb);
if (!ret)
break;
printf("%s",ret);
}
#endif
#ifdef SAMEASOTHER
int pid = fork();
if (pid == 0) {
signal(SIGHUP, SIG_DFL);
signal(SIGLLDB, SIG_DFL);
child = getpid();
int pfd[2] = {-1, -1};
if (isatty(STDIN_FILENO))
// If we are running on a terminal, then we need to bring process to foreground for input
// to work correctly on lldb's end.
bring_process_to_foreground();
else
// If lldb is running in a non terminal environment, then it freaks out spamming "^D" and
// "quit". It seems this is caused by read() on stdin returning EOF in lldb. To hack around
// this we setup a dummy pipe on stdin, so read() would block expecting "user's" input.
setup_dummy_pipe_on_stdin(pfd);
char lldb_shell[400]; char lldb_shell[400];
sprintf(lldb_shell, LLDB_SHELL); sprintf(lldb_shell, LLDB_SHELL);
@ -1218,7 +1094,6 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) {
perror("failed launching lldb"); perror("failed launching lldb");
close(pfd[0]); close(pfd[0]);
close(pfd[1]);
// Notify parent we're exiting // Notify parent we're exiting
kill(parent, SIGLLDB); kill(parent, SIGLLDB);
@ -1226,11 +1101,12 @@ void launch_debugger_and_exit(AMDeviceRef device, CFURLRef url) {
_exit(WEXITSTATUS(status)); _exit(WEXITSTATUS(status));
} else if (pid > 0) { } else if (pid > 0) {
child = pid; child = pid;
if (verbose)
printf("Waiting for child [Child: %d][Parent: %d]\n", child, parent);
} else { } else {
perror("fork failed"); perror("fork failed");
exit(exitcode_error); exit(exitcode_error);
} }
#endif
} }
CFStringRef get_bundle_id(CFURLRef app_url) CFStringRef get_bundle_id(CFURLRef app_url)
@ -1724,7 +1600,20 @@ void timeout_callback(CFRunLoopTimerRef timer, void *info) {
} }
else else
{ {
if (!debug)
printf("[....] No more devices found.\n"); printf("[....] No more devices found.\n");
else
{
int mypid = getpid();
if ((parent != 0) && (parent == mypid) && (child != 0))
{
if (verbose)
{
printf("Timeout. Killing child (%d) tree\n", child);
}
kill_ptree(child, SIGHUP);
}
}
exit(0); exit(0);
} }
} }