Skip to content

Commit 265c085

Browse files
guscshazron
authored andcommitted
feat: implement the stdout and stderr redirect to file (#339)
* Implement the stdout and stderr redirect to file * Separate output for stderr.
1 parent 087926f commit 265c085

File tree

3 files changed

+59
-3
lines changed

3 files changed

+59
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ If you are *not* using a node version manager like [nvm](https://github.com/crea
8787
-e, --exists check if the app with given bundle_id is installed or not
8888
-B, --list_bundle_id list bundle_id
8989
-W, --no-wifi ignore wifi devices
90+
-O, --output <file> write stdout and stderr to this file
9091
--detect_deadlocks <sec> start printing backtraces for all threads periodically after specific amount of seconds
9192

9293
## Examples

src/ios-deploy/ios-deploy.m

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
target create \"{disk_app}\"\n\
3333
script fruitstrap_device_app=\"{device_app}\"\n\
3434
script fruitstrap_connect_url=\"connect://127.0.0.1:{device_port}\"\n\
35+
script fruitstrap_output_path=\"{output_path}\"\n\
36+
script fruitstrap_error_path=\"{error_path}\"\n\
3537
target modules search-paths add {modules_search_paths_pairs}\n\
3638
command script import \"{python_file_path}\"\n\
3739
command script add -f {python_command}.connect_command connect\n\
@@ -66,6 +68,8 @@
6668
#include "lldb.py.h"
6769
;
6870

71+
const char* output_path = NULL;
72+
const char* error_path = NULL;
6973

7074
typedef struct am_device * AMDeviceRef;
7175
mach_error_t AMDeviceSecureStartService(AMDeviceRef device, CFStringRef service_name, unsigned int *unknown, ServiceConnRef * handle);
@@ -730,6 +734,21 @@ void write_lldb_prep_cmds(AMDeviceRef device, CFURLRef disk_app_url) {
730734
CFStringFindAndReplace(cmds, CFSTR("{device_port}"), device_port, range, 0);
731735
range.length = CFStringGetLength(cmds);
732736

737+
if (output_path) {
738+
CFStringRef output_path_str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), output_path);
739+
CFStringFindAndReplace(cmds, CFSTR("{output_path}"), output_path_str, range, 0);
740+
} else {
741+
CFStringFindAndReplace(cmds, CFSTR("{output_path}"), CFSTR(""), range, 0);
742+
}
743+
range.length = CFStringGetLength(cmds);
744+
if (error_path) {
745+
CFStringRef error_path_str = CFStringCreateWithFormat(NULL, NULL, CFSTR("%s"), error_path);
746+
CFStringFindAndReplace(cmds, CFSTR("{error_path}"), error_path_str, range, 0);
747+
} else {
748+
CFStringFindAndReplace(cmds, CFSTR("{error_path}"), CFSTR(""), range, 0);
749+
}
750+
range.length = CFStringGetLength(cmds);
751+
733752
CFURLRef device_container_url = CFURLCreateCopyDeletingLastPathComponent(NULL, device_app_url);
734753
CFStringRef device_container_path = CFURLCopyFileSystemPath(device_container_url, kCFURLPOSIXPathStyle);
735754
CFMutableStringRef dcp_noprivate = CFStringCreateMutableCopy(NULL, 0, device_container_path);
@@ -1777,6 +1796,8 @@ void usage(const char* app) {
17771796
@" -e, --exists check if the app with given bundle_id is installed or not \n"
17781797
@" -B, --list_bundle_id list bundle_id \n"
17791798
@" -W, --no-wifi ignore wifi devices\n"
1799+
@" -O, --output <file> write stdout to this file\n"
1800+
@" -E, --error_output <file> write stderr to this file\n"
17801801
@" --detect_deadlocks <sec> start printing backtraces for all threads periodically after specific amount of seconds\n"
17811802
@" -j, --json format output as JSON\n",
17821803
[NSString stringWithUTF8String:app]);
@@ -1825,13 +1846,15 @@ int main(int argc, char *argv[]) {
18251846
{ "exists", no_argument, NULL, 'e'},
18261847
{ "list_bundle_id", no_argument, NULL, 'B'},
18271848
{ "no-wifi", no_argument, NULL, 'W'},
1849+
{ "output", required_argument, NULL, 'O' },
1850+
{ "error_output", required_argument, NULL, 'E' },
18281851
{ "detect_deadlocks", required_argument, NULL, 1000 },
18291852
{ "json", no_argument, NULL, 'j'},
18301853
{ NULL, 0, NULL, 0 },
18311854
};
18321855
int ch;
18331856

1834-
while ((ch = getopt_long(argc, argv, "VmcdvunrILeD:R:i:b:a:t:p:1:2:o:l:w:9BWjNs:", longopts, NULL)) != -1)
1857+
while ((ch = getopt_long(argc, argv, "VmcdvunrILeD:R:i:b:a:t:p:1:2:o:l:w:9BWjNs:OE:", longopts, NULL)) != -1)
18351858
{
18361859
switch (ch) {
18371860
case 'm':
@@ -1937,6 +1960,12 @@ int main(int argc, char *argv[]) {
19371960
case 'W':
19381961
no_wifi = true;
19391962
break;
1963+
case 'O':
1964+
output_path = optarg;
1965+
break;
1966+
case 'E':
1967+
error_path = optarg;
1968+
break;
19401969
case 1000:
19411970
_detectDeadlockTimeout = atoi(optarg);
19421971
break;

src/scripts/lldb.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,16 @@ def autoexit_command(debugger, command, result, internal_dict):
8686
global listener
8787
process = lldb.target.process
8888

89+
output_path = internal_dict['fruitstrap_output_path']
90+
out = None
91+
if output_path:
92+
out = open(output_path, 'w')
93+
94+
error_path = internal_dict['fruitstrap_error_path']
95+
err = None
96+
if error_path:
97+
err = open(error_path, 'w')
98+
8999
detectDeadlockTimeout = {detect_deadlock_timeout}
90100
printBacktraceTime = time.time() + detectDeadlockTimeout if detectDeadlockTimeout > 0 else None
91101

@@ -97,14 +107,26 @@ def autoexit_command(debugger, command, result, internal_dict):
97107
def ProcessSTDOUT():
98108
stdout = process.GetSTDOUT(1024)
99109
while stdout:
100-
sys.stdout.write(stdout)
110+
if out:
111+
out.write(stdout)
112+
else:
113+
sys.stdout.write(stdout)
101114
stdout = process.GetSTDOUT(1024)
102115

103116
def ProcessSTDERR():
104117
stderr = process.GetSTDERR(1024)
105118
while stderr:
106-
sys.stdout.write(stderr)
119+
if err:
120+
err.write(stderr)
121+
else:
122+
sys.stdout.write(stderr)
107123
stderr = process.GetSTDERR(1024)
124+
125+
def CloseOut():
126+
if (out):
127+
out.close()
128+
if (err):
129+
err.close()
108130

109131
while True:
110132
if listener.WaitForEvent(1, event) and lldb.SBProcess.EventIsProcessEvent(event):
@@ -127,17 +149,21 @@ def ProcessSTDERR():
127149

128150
if state == lldb.eStateExited:
129151
sys.stdout.write( '\\nPROCESS_EXITED\\n' )
152+
CloseOut()
130153
os._exit(process.GetExitStatus())
131154
elif printBacktraceTime is None and state == lldb.eStateStopped:
132155
sys.stdout.write( '\\nPROCESS_STOPPED\\n' )
133156
debugger.HandleCommand('bt')
157+
CloseOut()
134158
os._exit({exitcode_app_crash})
135159
elif state == lldb.eStateCrashed:
136160
sys.stdout.write( '\\nPROCESS_CRASHED\\n' )
137161
debugger.HandleCommand('bt')
162+
CloseOut()
138163
os._exit({exitcode_app_crash})
139164
elif state == lldb.eStateDetached:
140165
sys.stdout.write( '\\nPROCESS_DETACHED\\n' )
166+
CloseOut()
141167
os._exit({exitcode_app_crash})
142168
elif printBacktraceTime is not None and time.time() >= printBacktraceTime:
143169
printBacktraceTime = None

0 commit comments

Comments
 (0)