Re: turning g_assert* into warnings
On Fri, 2007-10-12 at 11:52 +0200, Tim Janik wrote: i'd like to propose to turn g_assert and friends like g_assert_not_reached into warnings instead of errors. i'll give a bit of background before the details though. the main reasons we use g_return_if_fail massively throughout the glib and gtk+ code base is that it catches API misuses verbosely and gives programmers a chance to fix their code. this could be achieved with either a g_warning (mourn on stderr) or a g_error (mourn and abort). g_return_*if_fail() is a filter: I don't want crap to come into my library. As you said, it's intended for programmers to fix their code when they use libraries. g_assert(), on the other hand, is a hard pre/post-condition. It is if this is false, then my program is fucked up. There is *nothing* you can do... user data may already be corrupt or you will likely screw it up soon enough. It's better to crash right there. The idea is that you code libraries like this: int find_index_of_thingy (DataStructure *foo, Thingy thingy) { int i; Bar bar; g_return_val_if_fail (foo != NULL, -1); i = 0; bar = foo-bar; while (bar) { g_assert (bar-eek != NULL); if (are_the_same (thingy == bar-eek)) return i; i++; bar = next_bar (bar); } } I.e. if the public function gets called with bogus data, you return immediately and print a warning, so that the programmer will fix his code. It will probably crash anyway if the messy programmer didn't check the return value. On the other hand, the assertion is an internal sanity check within the library. If the data structure contains a NULL bar-eek, it *REALLY* means that something got fucked up earlier, and it's better to crash right there, because you don't know *WHAT* is corrupt. c) programs that aren't 100% bug free could possibly trigger these warnings during production. aborting would take all the end user data with it, created/modified images, text documents, etc. issuing just a warnig preserves the possibility to still save crucial data if the application logic state still permits (which is most often the case in practice). This is just a symptom of an unrobust program. You can't make a program more robust by ignoring error cases, which is what your proposal is about. You may make it more *resilient* temporarily, but by then who knows if you'll be saving bogus data. Programs which deal with critical data (I'd say any kind of document is critical) should really just implement auto-save. If the bug is in libsavemydata.so, well, life is hard... for a few reasons: 1) allow users to save their data if still possible; i.e. (c) from above. So... which program crashed on you, losing your unsaved data, which caused you to start this discussion? :) 2) for glib/gtk+ unit tests (more on that later), failing but non-aborting tests are interesting for overall report generation; and the ability to force immediate aborts for debugging is preserved with --g-fatal-warninngs. *shrug*. A crashed test means the test suite failed :) It may be mildly interesting to know the test suite failed because test_123() would have crashed, but why would you be releasing with test suites that don't pass, anyway? 3) assertions can help to document programmer intentions and frequent (but regulated) use as we have it with g_return_if_fail can significantly reduce debugging time. i have so far been fairly strict about not adding assertions to the glib/gtk+ core though, because they also tend to make the code and end-user experiences more brittle, especially an occasional wrong assertions that'd have to be revoked upon closer inspection. A wrong assertion is just a bug like any other. It means uuh, I wasn't sure of the state my program may be in at this point, so I'll assert() that it has the state I think it should have, and I'll fix it if it crashes later. It just indicates a sloppy programmer who should have used a test suite with better code coverage :) I've been guilty of wrong assertions in the past, and the description above is *exactly* what happened to me --- laziness to *really* figure out the implications of the code flow. as a side note, it'd probably make sense to present the end users with more prominent warnings if one of his applications ran into a glib warning/ critical/assertion, and he should be notified about needing to save his data and exit ASAP. but that's really another topic, probably best tackled by gnome. That's actually a nice idea, and would help get problems like fooapp spews thousands of the same g_warning() and .xsession-errors fills up fixed more quickly. Federico ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
hi, Marco Barisione schrieb: Il giorno ven, 12/10/2007 alle 15.16 +0200, Tim Janik ha scritto: please reread my reasoning about G_DISABLE_ASSERT, there already is no behavior of g_assert() you could rely on. (and some distributions do build their binaries with G_DISABLE_ASSERT and/or G_DISABLE_CHECKS defined). What distributions? Excluding Gentoo and other distros that allow the user to choose how to build everything. we actually considered this several times for maemo. If the app runs into g_assert it disappears, if the g_assert is disabled it usually disappears a bit later when it segfaults. for the user it makes no visual difference - the application died. For the developer it makes sense as the assert help to track it down. For pure user systems (in the embedded area) it makes sense to disable the asserts (for performance reasons). Stefan ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
turning g_assert* into warnings
hey All. i'd like to propose to turn g_assert and friends like g_assert_not_reached into warnings instead of errors. i'll give a bit of background before the details though. the main reasons we use g_return_if_fail massively throughout the glib and gtk+ code base is that it catches API misuses verbosely and gives programmers a chance to fix their code. this could be achieved with either a g_warning (mourn on stderr) or a g_error (mourn and abort). the reasons for the default behavior to use g_warning: a) a warning usually fullfills its purpose, the programmer knows there's something to fix and can start to trace the root cause. b) for easy tracing in gdb with backtraces, programmers can use --g-fatal-warnings to force abort behavior. c) programs that aren't 100% bug free could possibly trigger these warnings during production. aborting would take all the end user data with it, created/modified images, text documents, etc. issuing just a warnig preserves the possibility to still save crucial data if the application logic state still permits (which is most often the case in practice). in a recent discussion, i figured that (c) perfectly applies to g_assert and g_assert_if_reached() also. but we're actually aborting here: void g_assert_warning ([...]) { [...] abort (); } i'd like to change that to: void g_assert_warning ([...]) { [...] - abort (); + if (--g-fatal-warninngs) + abort (); } for a few reasons: 1) allow users to save their data if still possible; i.e. (c) from above. 2) for glib/gtk+ unit tests (more on that later), failing but non-aborting tests are interesting for overall report generation; and the ability to force immediate aborts for debugging is preserved with --g-fatal-warninngs. 3) assertions can help to document programmer intentions and frequent (but regulated) use as we have it with g_return_if_fail can significantly reduce debugging time. i have so far been fairly strict about not adding assertions to the glib/gtk+ core though, because they also tend to make the code and end-user experiences more brittle, especially an occasional wrong assertions that'd have to be revoked upon closer inspection. conditionalizing the abort removes the brittleness and allows for adding more helpful assertion statements. note that in practice, this shouldn't change anything for programmers (except for the ability to write better code ;) because of G_DISABLE_ASSERT, programmers can already not rely on failing assertions to abort their programs (only g_error will reliably do that). it should however take down programs in end user scenarios less often, and code review can be more lax about adding assertions. as a side note, it'd probably make sense to present the end users with more prominent warnings if one of his applications ran into a glib warning/ critical/assertion, and he should be notified about needing to save his data and exit ASAP. but that's really another topic, probably best tackled by gnome. comments welcome and thanks for the interest. --- ciaoTJ ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
Am Freitag, den 12.10.2007, 11:52 +0200 schrieb Tim Janik: note that in practice, this shouldn't change anything for programmers (except for the ability to write better code ;) because of G_DISABLE_ASSERT, programmers can already not rely on failing assertions to abort their programs (only g_error will reliably do that). I was in strict HELL, NO! mode until I read this reasoning. Still I am not sure if G_DISABLE_ASSERT is a misfeature, since when using g_assert* instead of g_return* or g_warning you usually really have no good fallback strategy and therefore accept the program crashing. So for better error handling I'd suggest keeping the old and boring if (blub) { g_warning ... } paradigm. Also remember that such a dramatic that (external) programmers most certainly do not expect their program to continue after a failed assertion (despite the G_DISABLE_ASSERT misfeature). So not calling abort on failed assertions could make the program eat little children, if not worse. So I guess what you really want is some kind of g_soft_assert or some g_warn_if_fail. Ciao, Mathias -- Mathias Hasselmann [EMAIL PROTECTED] http://taschenorakel.de/ signature.asc Description: Dies ist ein digital signierter Nachrichtenteil ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
Hey, Why not introduce a new check, some g_check_stuff() which would do what you propose? And let g_assert() be what it is, a glib analog of C assert(). When an assertion fails, you can't possibly expect the code to function in any meaningful way, e.g. int idx; g_assert (idx = 0); array[idx] = 8; you get segfault or worse here if g_assert() above fails to bring program down, you simply can't change g_assert() now to behave in such a different way. Often you indeed can do sensible things after some important assumption happened to be false, and in those situations a new check would be really cool (where existing code does manual checks like if (bad) {g_critical (oops); emergency_return_or_whatever();} ). But it should be a programmer decision, and it's just not acceptable to change behavior of existing code. Best regards, Yevgen Tim Janik wrote: hey All. i'd like to propose to turn g_assert and friends like g_assert_not_reached into warnings instead of errors. i'll give a bit of background before the details though. the main reasons we use g_return_if_fail massively throughout the glib and gtk+ code base is that it catches API misuses verbosely and gives programmers a chance to fix their code. this could be achieved with either a g_warning (mourn on stderr) or a g_error (mourn and abort). the reasons for the default behavior to use g_warning: a) a warning usually fullfills its purpose, the programmer knows there's something to fix and can start to trace the root cause. b) for easy tracing in gdb with backtraces, programmers can use --g-fatal-warnings to force abort behavior. c) programs that aren't 100% bug free could possibly trigger these warnings during production. aborting would take all the end user data with it, created/modified images, text documents, etc. issuing just a warnig preserves the possibility to still save crucial data if the application logic state still permits (which is most often the case in practice). in a recent discussion, i figured that (c) perfectly applies to g_assert and g_assert_if_reached() also. but we're actually aborting here: void g_assert_warning ([...]) { [...] abort (); } i'd like to change that to: void g_assert_warning ([...]) { [...] - abort (); + if (--g-fatal-warninngs) + abort (); } for a few reasons: 1) allow users to save their data if still possible; i.e. (c) from above. 2) for glib/gtk+ unit tests (more on that later), failing but non-aborting tests are interesting for overall report generation; and the ability to force immediate aborts for debugging is preserved with --g-fatal-warninngs. 3) assertions can help to document programmer intentions and frequent (but regulated) use as we have it with g_return_if_fail can significantly reduce debugging time. i have so far been fairly strict about not adding assertions to the glib/gtk+ core though, because they also tend to make the code and end-user experiences more brittle, especially an occasional wrong assertions that'd have to be revoked upon closer inspection. conditionalizing the abort removes the brittleness and allows for adding more helpful assertion statements. note that in practice, this shouldn't change anything for programmers (except for the ability to write better code ;) because of G_DISABLE_ASSERT, programmers can already not rely on failing assertions to abort their programs (only g_error will reliably do that). it should however take down programs in end user scenarios less often, and code review can be more lax about adding assertions. as a side note, it'd probably make sense to present the end users with more prominent warnings if one of his applications ran into a glib warning/ critical/assertion, and he should be notified about needing to save his data and exit ASAP. but that's really another topic, probably best tackled by gnome. comments welcome and thanks for the interest. --- ciaoTJ ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
c) programs that aren't 100% bug free could possibly trigger these warnings during production. aborting would take all the end user data with it, created/modified images, text documents, etc. issuing just a warnig preserves the possibility to still save crucial data if the application logic state still permits (which is most often the case in practice). in a recent discussion, i figured that (c) perfectly applies to g_assert and g_assert_if_reached() also. but we're actually aborting here: One problem i see is that g_return_if_fail() also does something, ie returns, which can act as a sufficient fallback in many cases. Another tradeoff is that while you may be able to save something, it may be corrupted. my recent work (on journalling databases) has seen a lot of cases where assertions prevented corruption from making it to disk, allowing an earlier state to be resumed. but that may be less common on the desktop. Finally, i do think it's a pretty big break with the traditional definition of assert(). - dave ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
On Fri, 12 Oct 2007, Yevgen Muntyan wrote: Hey, Why not introduce a new check, some g_check_stuff() which would do what you propose? And let g_assert() be what it is, a glib analog of C assert(). When an assertion fails, you can't possibly expect the code to function in any meaningful way, e.g. int idx; g_assert (idx = 0); array[idx] = 8; you get segfault or worse here if g_assert() above fails to bring program down, you simply can't change g_assert() now to behave in such a different way. please reread my reasoning about G_DISABLE_ASSERT, there already is no behavior of g_assert() you could rely on. (and some distributions do build their binaries with G_DISABLE_ASSERT and/or G_DISABLE_CHECKS defined). if you really meant the above assertion as an essential program logic part and want to depend on the program exiting before array[] is accessed, you already have to use if (idx = 0) g_error (off bounds); Best regards, Yevgen --- ciaoTJ ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
On Fri, 2007-10-12 at 14:40 +0200, Mathias Hasselmann wrote: So I guess what you really want is some kind of g_soft_assert or some g_warn_if_fail. +1 on a g_warn_if_fail() API addition. ciao, Emmanuele. -- Emmanuele Bassi, W: http://www.emmanuelebassi.net B: http://log.emmanuelebassi.net ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
Tim Janik wrote: hey All. i'd like to propose to turn g_assert and friends like g_assert_not_reached into warnings instead of errors. i'll give a bit of background before the details though. Like Mathias, I was in a bit of hell no! mode when I first read this. After reading your rationale, I'm less opposed, but... well, still opposed. the main reasons we use g_return_if_fail massively throughout the glib and gtk+ code base is that it catches API misuses verbosely and gives programmers a chance to fix their code. this could be achieved with either a g_warning (mourn on stderr) or a g_error (mourn and abort). the reasons for the default behavior to use g_warning: a) a warning usually fullfills its purpose, the programmer knows there's something to fix and can start to trace the root cause. b) for easy tracing in gdb with backtraces, programmers can use --g-fatal-warnings to force abort behavior. c) programs that aren't 100% bug free could possibly trigger these warnings during production. aborting would take all the end user data with it, created/modified images, text documents, etc. issuing just a warnig preserves the possibility to still save crucial data if the application logic state still permits (which is most often the case in practice). This is reasonable, and pretty much covers why I use g_return_if_fail() and friends. in a recent discussion, i figured that (c) perfectly applies to g_assert and g_assert_if_reached() also. Sorry, but I just don't buy it. When I use g_assert(), my thinking is: this is something that's a pretty bad bug on my part, and if the assertion fails, I'm almost 100% sure that the program is going to crash very very soon, and possibly in unpredictable ways. for a few reasons: 1) allow users to save their data if still possible; i.e. (c) from above. If I think it's possible for users to still do something meaningful with the program, I'll use a g_return_if_fail() or a custom if(foo) { g_warning(); do_something(); } type thing. That's why we have the separate macros in the first place! g_return*() are for cases where the programmer thinks recovery might be possible, and g_assert*() is where it isn't possible. 3) assertions can help to document programmer intentions and frequent (but regulated) use as we have it with g_return_if_fail can significantly reduce debugging time. i have so far been fairly strict about not adding assertions to the glib/gtk+ core though, because they also tend to make the code and end-user experiences more brittle, especially an occasional wrong assertions that'd have to be revoked upon closer inspection. And that's the right approach, IMO: use assertions sparingly. Sometimes one might be a mistake, and you fix it. conditionalizing the abort removes the brittleness and allows for adding more helpful assertion statements. No, it doesn't. Changing a g_assert*() to a g_return*() when you realise aborting is unnecessary is the way to go. note that in practice, this shouldn't change anything for programmers (except for the ability to write better code ;) because of G_DISABLE_ASSERT, programmers can already not rely on failing assertions to abort their programs (only g_error will reliably do that). ... which I think is pretty broken. You shouldn't be able to disable asserts and pre-condition checks (G_DISABLE_CHECKS) at compile time. They were put there for a reason. it should however take down programs in end user scenarios less often, and code review can be more lax about adding assertions. No -- instructing programmers to make *proper* use of g_assert*() (and to use g_return*() otherwise) will bring programs down less often. Or maybe not -- maybe everyone uses it properly and this problem you just doesn't exist. Also... The documentation tells us what g_return*() and g_assert*() do. If you change this, you're essentially changing the API of glib. That's... not cool. You can argue that G_DISABLE_CHECKS and G_DISABLE_ASSERT will do this anyway, but that's a choice on the person who builds the code (and again, I'd argue that the existence of those defines is a *really* bad idea). IMO, if you build with G_DISABLE_(CHECKS|ASSERTS), you get to keep the pieces when things break. -brian ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
2007/10/12, Tim Janik [EMAIL PROTECTED]: hey All. i'd like to propose to turn g_assert and friends like g_assert_not_reached into warnings instead of errors. i'll give a bit of background before the details though. [snip] While the reasoning to make programs seem less crashy sounds compelling, isn't this just admitting that developers are misusing the g_assert* macros and Glib will bow down and disable functionality due to this? The macros are very clearly stated as fatal to the application in the documentation, so they should be used very carefully and only when *any* part of the program cannot function properly due to that condition being false. If an application is terminating while it still has a chance to save data, I'd say it is a bug in the application. It should either automatically do so before quitting or advice the user to perform those two tasks to prevent data loss. And libraries naturally should IMO _never_ use g_assert* in the first place, since libraries should never be in charge of application lifetime no matter how bad their internal state is. So I'd vote no for circumventing API misuse, no matter how wide it is. Distributors could start disabling assertions in their builds if they feel that it is compelling enough to warrant it, and as said, development builds (ie. all from the source installations) should always have clear indications of bugs. The macros probably could use more clear usage suggestions in the documentation though, mentioning the fact that using them in a library is usually just unfriendly to application developers since it prevents craceful termination even if it would be possible. -- Kalle Vahlman, [EMAIL PROTECTED] Powered by http://movial.fi Interesting stuff at http://syslog.movial.fi ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
Il giorno ven, 12/10/2007 alle 15.16 +0200, Tim Janik ha scritto: please reread my reasoning about G_DISABLE_ASSERT, there already is no behavior of g_assert() you could rely on. (and some distributions do build their binaries with G_DISABLE_ASSERT and/or G_DISABLE_CHECKS defined). What distributions? Excluding Gentoo and other distros that allow the user to choose how to build everything. -- Marco Barisione http://www.barisione.org/ ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
That's pretty much a no-go. g_assert_warning is marked G_GNUC_NORETURN. If you return from such a function, there is no telling what incorrect assumption the following code was compiled with, i.e., things that the compiler thought were in registers all of a sudden are not. Crash. Burn. Toast. If you remove G_GNUC_NORETURN, you are going to get an unpleasant number of might/is used uninitialized warnings. And if you do return, you get the same problems with bad assumptions as above, only this time in the client program. All of this leads to the conclusion that g_asserts should be used sparingly, i.e., for things where the program is in a really bad shape and has no idea about how to limp on. Morten ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
On Fri, 12 Oct 2007, Owen Taylor wrote: On Fri, 2007-10-12 at 11:52 +0200, Tim Janik wrote: i'd like to propose to turn g_assert and friends like g_assert_not_reached into warnings instead of errors. i'll give a bit of background before the details though. This is an incompatible change. The contract now is that unless you compile with G_DISABLE_ASSERT, g_assert(FALSE) will cause your program to exit with a non-zero status. i don't think a function contract is anything worth if it depends on build time options. if there is any contract breach here, it was the introduction of G_DISABLE_ASSERT (Thu Feb 19 01:11:48 1998 in gtk+-0.99.4 ;) however, due to the g_warn_if_fail variant having quite a following, i intend to change my proposal anyway. so persuing this argument is moot. - Owen --- ciaoTJ ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
On Fri, 2007-10-12 at 11:52 +0200, Tim Janik wrote: i'd like to propose to turn g_assert and friends like g_assert_not_reached into warnings instead of errors. i'll give a bit of background before the details though. This is an incompatible change. The contract now is that unless you compile with G_DISABLE_ASSERT, g_assert(FALSE) will cause your program to exit with a non-zero status. The fact that you *could* fix up 'make test' (for GLib, etc, etc, etc) by making warnings terminate the program doesn't help. It's still incompatible. - Owen signature.asc Description: This is a digitally signed message part ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
On 10/12/07, Emmanuele Bassi [EMAIL PROTECTED] wrote: On Fri, 2007-10-12 at 14:40 +0200, Mathias Hasselmann wrote: So I guess what you really want is some kind of g_soft_assert or some g_warn_if_fail. +1 on a g_warn_if_fail() API addition. What is wrong with: if (!everything_is_ok) g_warning (blaha); ? Those double or triple negatives that the *_if_fail routines introduce always confuses me: g_return_if_fail (!(flag != SOMETHING x)); ugh.. -- mvh Björn ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: turning g_assert* into warnings
BJörn Lindqvist wrote: On 10/12/07, Emmanuele Bassi [EMAIL PROTECTED] wrote: On Fri, 2007-10-12 at 14:40 +0200, Mathias Hasselmann wrote: So I guess what you really want is some kind of g_soft_assert or some g_warn_if_fail. +1 on a g_warn_if_fail() API addition. What is wrong with: if (!everything_is_ok) g_warning (blaha); ? Those double or triple negatives that the *_if_fail routines introduce always confuses me: g_return_if_fail (!(flag != SOMETHING x)); ugh.. You messed it up somehow. It's never triple, since our normal logic is either yes or no, the max is double negative which is positive. Your example would be some g_warn_if_fail (everything_is_ok, blaha); nothing fancy. ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list