Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stdout , stderr redirection and related issues #130

Closed
xandro0777 opened this issue Oct 12, 2021 · 10 comments · Fixed by #132
Closed

stdout , stderr redirection and related issues #130

xandro0777 opened this issue Oct 12, 2021 · 10 comments · Fixed by #132

Comments

@xandro0777
Copy link

I tried to redirect stdout+stderr to a file like this:

fn C.freopen(filename &char, mode &char, stream &C.FILE) &C.FILE
fn C.perror(message &char)

...
...

	file := C.freopen('/sdcard/v-log.txt'.str, c'w', C.stdout)
	if file == C.NULL {
		err := C.errno
		C.perror('problem reopening'.str)
		println('problem reopening: $err')
	}

	C.dup2(1, 2)

Apparently that fails with EACCES because the app doesn't have the permission. not unexpected.
However, the C.perror() message doesn't come, while the println does its job. What could be the problem?

@xandro0777
Copy link
Author

after fixing the issue with the permission the file is created - but println() still writes to syslog instead of writing to my file :(

Any idea what did go wrong there or how to debug?

@xandro0777
Copy link
Author

after digging into it I am a bit surprised that the output of VAB apps goes into system logs at all. Stackoverflow and other places mention that stdout and stderr from NDK apps goes to /dev/null - which would be the behaviour I see with C.perror()

@Larpon
Copy link
Contributor

Larpon commented Oct 13, 2021

Only thing I know is that we override printf in a macro

@xandro0777
Copy link
Author

xandro0777 commented Oct 13, 2021 via email

@Larpon
Copy link
Contributor

Larpon commented Oct 14, 2021

It was made initially to speed up development on Android - since otherwise I had to work "in the dark" which wasn't fun 😅 I'm still not sure what we should do to make a better solution.

It's nice for developers to be able to use println and eprintln seamlessly on Android while developing apps. Maybe we can use some compiletime define to switch it off 🤔

@xandro0777
Copy link
Author

Not sure either.

Redirecting stdin and stderr to a file on /sdcard like I did is easy and has the advantage that the output can be examined without adb and all low-level io output routines work as well.

To send stdout etc to syslog properly people do complicated things like https://codelab.wordpress.com/2014/11/03/how-to-use-standard-output-streams-for-logging-in-android-apps/ This has the advantage that it catches all output unlike the current macro hack and if someone like me wants to redirect it to a file it should work just like on Linux. The only disadvantage is complexity.. never tried it myself and not sure how robust that is.

The current hack is good enough most of the time but it would be nice if it would switch real printf and android logging based for example on a global c variable. The way the macro interacts with the print definition in builtin/buitlin.c.v is fairly convoluted so I am not sure how to do it but perhaps something like

	#define printf(...) {if (_use_log_io){__android_log_print(ANDROID_LOG_INFO, V_ANDROID_LOG_TAG_NAME, __VA_ARGS__)}else{printf(__VA_ARGS)}}
	#define fprintf(a, ...)  {if (_use_log_io){__android_log_print(ANDROID_LOG_ERROR, V_ANDROID_LOG_TAG_NAME, __VA_ARGS__)}else{fprintf(a,__VA_ARGS)}}

This would have the advantage that something would always work and is easy enough to revert to "normal" behavior.

@xandro0777
Copy link
Author

I did test the last variant - use a global c variable to switch between current redirect to log macro and normal stdout/stderr output which can be redirected as expected. So unless the developer does C._use_log_io = 0 in his app the behavior will stay as before. It would have been slightly easier to achieve with conditional compilation but I believe switching the behavior at runtime is more useful as it can catch errors happening before the redirection is established.

The patch bellow does that, the only little problem is that it generates an innocent warning which I haven't yet figured out how to fix. Please feel free to reuse and improve, no copyright considerations attached.

diff --git a/thirdparty/sokol/sokol_v.h b/thirdparty/sokol/sokol_v.h
index cc086789..2880ba9a 100644
--- a/thirdparty/sokol/sokol_v.h
+++ b/thirdparty/sokol/sokol_v.h
@@ -13,8 +13,11 @@
 
        #define V_ANDROID_LOG_TAG_NAME V_ANDROID_LOG_NAME(V_ANDROID_LOG_TAG)
 
+        extern int _use_log_io;
        #include <android/log.h>
-       #define printf(...) __android_log_print(ANDROID_LOG_INFO, V_ANDROID_LOG_TAG_NAME, __VA_ARGS__)
-       #define fprintf(a, ...) __android_log_print(ANDROID_LOG_ERROR, V_ANDROID_LOG_TAG_NAME, __VA_ARGS__)
+#define printf(...) {if (_use_log_io){__android_log_print(ANDROID_LOG_INFO, V_ANDROID_LOG_TAG_NAME, __VA_ARGS__);}else{printf(__VA_ARGS__);}}
+#define fprintf(a, ...)  {if (_use_log_io){__android_log_print(ANDROID_LOG_ERROR, V_ANDROID_LOG_TAG_NAME, __VA_ARGS__);}else{fprintf(a,__VA_ARGS__);}}
+//#define printf(...) __android_log_print(ANDROID_LOG_INFO, V_ANDROID_LOG_TAG_NAME, __VA_ARGS__)
+//#define fprintf(a, ...) __android_log_print(ANDROID_LOG_ERROR, V_ANDROID_LOG_TAG_NAME, __VA_ARGS__)
 #endif
 
diff --git a/vlib/builtin/builtin.c.v b/vlib/builtin/builtin.c.v
index 0379c833..8a52c4d3 100644
--- a/vlib/builtin/builtin.c.v
+++ b/vlib/builtin/builtin.c.v
@@ -5,6 +5,10 @@ type FnExitCb = fn ()
 fn C.atexit(f FnExitCb) int
 fn C.strerror(int) &char
 
+$if android {
+       C._use_log_io = 1
+}
+
 [noreturn]
 fn vhalt() {
        for {}

To redirect stdout/stderr from an app to a file on SDCARD you could do something like

	file := C.freopen('/sdcard/v-log.txt'.str, c'w', C.stdout)
	if file == C.NULL {
		err := C.errno
		println('problem reopening: $err')
	}

	C.dup2(1, 2)
	C._use_log_io = 0

@xandro0777 xandro0777 changed the title perror does not seem to work? stdout , stderr redirection and related issues Oct 18, 2021
@Larpon
Copy link
Contributor

Larpon commented Oct 22, 2021

@xandro0777 - I'm trying to figure out how we fix it the best way. My initial idea is to disable it in V itself and then enable it in vab per default - and then add a flag to vab: vab --no-printf-hijack to let you bypass the default behaviour.

The reason for not disabling it per default is that it's used a lot by developers and is somewhat expected for end-users that println('...') will end up in the android logs - and not in some black hole where they have to resort to reading the docs :)

Later I can add it as an ENV flag (maybe when I get to #125 ) and via .vab files etc.

@xandro0777
Copy link
Author

xandro0777 commented Oct 22, 2021 via email

@Larpon
Copy link
Contributor

Larpon commented Oct 22, 2021

Right. 🤔 let's start out with just the define/flag switch. I've PR'ed the initial changes to V - we'll see if anyone has any better ideas 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants