1. Си / Говнокод #6349

    +147

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    void
    syslog(int pri, const char *fmt, ...)
    {
    	va_list ap;
    
    	va_start(ap, fmt);
    	vsyslog(pri, fmt, ap);
    	va_end(ap);
    }
    ......................................
    void
    vsyslog(int pri, const char *fmt, va_list ap)
    {
    	vsyslog_r(pri, &sdata, fmt, ap);
    }
    ....................................
    void
    vsyslog_r(int pri, struct syslog_data *data, const char *fmt, va_list ap)
    {
    	int cnt;
    	char ch, *p, *t;
    	time_t now;
    	int fd, saved_errno, error;
    #define	TBUF_LEN	2048
    #define	FMT_LEN		1024
    	char *stdp = NULL, tbuf[TBUF_LEN], fmt_cpy[FMT_LEN];
    	int tbuf_left, fmt_left, prlen;
    
    #define	INTERNALLOG	LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
    	/* Check for invalid bits. */
    	if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
    		if (data == &sdata) {
    			syslog(INTERNALLOG,
    			    "syslog: unknown facility/priority: %x", pri);
    		} else {
    			syslog_r(INTERNALLOG, data,
    			    "syslog_r: unknown facility/priority: %x", pri);
    		}
    		pri &= LOG_PRIMASK|LOG_FACMASK;
    	}
    .......................
    }
    ......................

    Из исходников Bioninc - Android libc.
    В реализации сислога, в случае ошибки, вызывается syslog

    Запостил: elenbert, 14 Апреля 2011

    Комментарии (5) RSS

    • Это волшебно.
      Ответить
    • yo dawg i heard you like logging so we put a syslog in your syslog so you can log errors while you log errors
      Ответить
    • Ну вы вообще-то должны были догадаться по названиям функций, что автор кода прекрасно понимал необычность выбранного подхода и степень осторожности, которую надо соблюсти. По-видимому постфикс '_r' предназначен именно для потенциально "рекурсивных" вызовов, а также проверки 'data == &sdata' тоже скорее всего призваны отлавливать соответствующие проблемы. Но судить о том, насколько правильно это реализовано, трудно, ибо полного кода вы не привели и нескольких критически важных определений не хватает.

      Другими словами, ваше заявление о том, что "сислог вызывает сислог" просто напросто говорит о том, что вы, не разобравшись, упростили ситуацию. Тут скорее всего "спрятано" два сислога: низкоуровневый и высокоуровневый. Высокоуровневый, по задумке, должен вызывать низкоуровневый или что-то в этом роде. Автор, скорее всего, пытался сделать все через одну точку входа и получил в результате чересчур запутанный код. Выглядит, конечно, криво.
      Ответить
      • Может быть.
        Собственно исходники андроида не представляют собой тайны:
        http://android.git.kernel.org/?p=platform/bionic.git;a=blob_plain;f=libc/unistd/syslog.c;hb=HEAD
        Ответить
      • _r обычно означает reentrant и используется для функций, не зависящих от глобальных данных (в данном случае &sdata).

        Проверка data == &sdata служит исключительно для отличения syslog от syslog_r в логе (можно было бы записать короче и не так стрёмно).

        Рекурсия здесь не больше 2 в глубину, потому, что происходит при установленных левых битах, а повторный вызов идёт с гарантированно правильными флагами.

        Так что всё правильно работает. Но вот #define в середине функции попахивает.
        Ответить

    Добавить комментарий