מאמרים בנושא ‏לינוקס‏.

שוחררה גרסת 0.0.5 של CppCMS (ענף יציב)

ב־יום שני, 11 בינואר 2010, מאת ארתיום; פורסם תחת: תכנה חופשית, אינטרנט, לינוקס, פיתוח, תכנה ומחשבים, CppCMS, C++‎‏; ‏2 תגובות

שוחררה גרסה חדשה של ענף יציב של CppCMS, שינויים:

תיקוני בעיות אבטחה:

  • נכתב מעקף לבעיה של ספריית CgiCC שהיה יכול לגרום ל־DoS.
  • תוקנה בעיה שהייתה עלולה לגרום להווצרות SID בעלי אנטרופיה נמוכה.

תיקוני באגים:

  • תוקן זמן חיים של ערכים "חשופים" בניהול מצב (sessions)
  • תוקן באג שמנע אפשרות עבודה ב־FastCGI/SCGI מעל TCP/IP
  • תוקנו בעיות בניה עם גרסאות Boost לא סטנדרטיות.
  • תוקנו בעיות ביצירת HTTP Status Headers לא נכונים במקרה של שגיאות.
  • תוקנו בעיות בניה עם גרסאות gcc שונות ועם קומפיילר של אינטל.

שיפורים:

  • שופרו זמני בעיות views בצורה משמעות.

ייסורי בינאום ולוקליזציה בשנת 2009

ב־יום שלישי, 6 באוקטובר 2009, מאת ארתיום; פורסם תחת: תכנה חופשית, לינוקס, פיתוח, תכנה ומחשבים, C++‎‏, Unicode; ‏0 תגובות

מה יותר פשוט מאשר להציג תאריך ושעה בהתאם למקובל באיזור? בארה"ב תכתוב ‎6/15/2008 8:30 PM ובישראל תכתוב 15/6/2008 20:30. לא מסובך, נכון? כמובן ‎strftime‎ עושה את העבודה הנאמנה בצורה טובה. אכן, יש אופציות ‎"%x"‎ ו־‎"%X"‎ להצגת תאריך ושעה בהתאם ללוקל מקומי.

עכשיו בואו נעשה את הדרך ההפוכה: יש לנו טופס HTML בו אנחנו רוצים להציג תאריך ולתת למשתמש אפשרות לערוך אותו? במילים אחרות אני רוצה אופציה של פענוח תאריך ושעה לפי התבנית המקובלת לאיזור ובשפה הספציפיים... ואכן, יש פונקציה הפוכה ל־strftime ‏--- strptime. שעושה את העבודה ההפוכה.

כמובן גם ב־C++‎ יש מקבילות std::facet מסוג: std::time_put ו־std::time_get עושות את העבודה וגם מאפשרות להשתמש ביותר מ־locale אחד בתהליך, שמאפשר, למשל לייצר טקסט שונה למשתמשים שונים בחוטים שונים. ב־C ובשירותי מערכת ההפעלה הסטנדרטיים אין כלי כזה, יש רק strftime_l ו־strptime_l הלא מתועדים ולא מוגדרים לפי סטנדרט שעושים את העבודה.

מכאן, הכל פשוט... על הנייר. במציאות המצב הרבה יותר מסובך:

  • הגדרות סטנדרט C++‎ של std::time_get מכילות באג לוגי שמקשה מאוד על יצירת כלים לפענוח תאריך ושעה בצורה נכונה וגם כשעובדים, הם עושים זאת בצורה חלקית --- כי אין מקבילה של strptime המלאה של C.
  • גם API של C, מסתבר כלא תמיד עובד כמו שצריך.

לצורך ההשוואה, בניתי תכנה פשוטה, שמייצרת מחרוזת עם תאריך ושעה בעזרת כלֵי C,‏ C++‎ וספריית ICU. ולאחר מכן מפענחת אותה אם אותם הכלים. בדקתי את זה עבור מספר לוקלים. בטבלה למטה מוצגים: לוקל, שעה ותאריך כפי שמייוצרים ע"י כלים שונים והפענוח של אותם תאריך ושעה המוצגים בפורמט בינלאומי.

    en_US.UTF-8
    strftime        10/05/2009 11:36:38 PM to 2009-10-05 23:36:38
    std::facet      10/05/2009 11:36:38 PM to 2009-10-05 00:00:00
    icu::DateFormat Oct 5, 2009 11:36:38 PM to 2009-10-05 23:36:38
    he_IL.UTF-8
    strftime        05/10/09 23:36:38 to 2009-10-05 23:36:38
    std::facet      05/10/09 23:36:38 to 1909-10-05 23:36:38
    icu::DateFormat 23:36:38 05/10/2009 to 2009-10-05 23:36:38
    de_DE.UTF-8
    strftime        05.10.2009 23:36:38 to 2009-10-05 23:36:38
    std::facet      05.10.2009 23:36:38 to 2009-10-05 23:36:38
    icu::DateFormat 05.10.2009 23:36:38 to 2009-10-05 23:36:38
    en_GB.UTF-8
    strftime        05/10/09 23:36:38 to 2009-10-05 23:36:38
    std::facet      05/10/09 23:36:38 to 1909-10-05 23:36:38
    icu::DateFormat 5 Oct 2009 23:36:38 to 2009-10-05 23:36:38
    ja_JP.UTF-8
    strftime        2009年10月05日 23時36分38秒 to 2009-10-05 23:36:38
    std::facet      2009年10月05日 23時36分38秒 to 2009-10-05 23:36:38
    icu::DateFormat 2009/10/05 23:36:38 to 2009-10-05 23:36:38
    ar_EG.UTF-8
    strftime        05 أكت, 2009 IST 11:36:38  to 2009-10-05 00:00:00
    std::facet      05 أكت, 2009 IST 11:36:38  to 2009-10-05 11:36:38
    icu::DateFormat ٠٥/١٠/٢٠٠٩ ١١:٣٦:٣٨ م to 2009-10-05 23:36:38
    tr_TR.UTF-8
    strftime        05-10-2009 23:36:38 to 2009-10-05 23:36:38
    std::facet      05-10-2009 23:36:38 to 2009-10-05 23:36:38
    icu::DateFormat 05.Eki.2009 23:36:38 to 2009-10-05 23:36:38
    ru_RU.UTF-8
    strftime        05.10.2009 23:36:38 to 2009-10-05 23:36:38
    std::facet      05.10.2009 23:36:38 to 2009-10-05 23:36:38
    icu::DateFormat 05.10.2009 23:36:38 to 2009-10-05 23:36:38
    zh_CN.UTF-8
    strftime        2009年10月05日 23时36分38秒 to 2009-10-05 23:36:38
    std::facet      2009年10月05日 23时36分38秒 to 2009-10-05 23:36:38
    icu::DateFormat 2009-10-5 下午11:36:38 to 2009-10-05 23:36:38

כפי שניתן לראות:

  • std::facet לא מתמודד עם שעון של 12 שעות המכיל ציון AM/PM.‏
  • std::facet לא מוסוגל לשחזר שנה בעזרת שתי ספרות בלבד וזורק אותנו משנת 2009 ל־1909 ב־2 מתוך 9 דוגמאות.
  • strptime לא מצליח לשחזר שעה בכלל ו־std::facet וטועה ב־12 שעות בלוקל מצרי.יש לציין שזה באג בייצוג locale כי הפורמט המוגדר הוא ‎"%Z %I:%M:%S"‎ במקום ‎"%p %I:%M:%S"‎ --- להציג איזור זמן במקום סימון AM/PM המתאים (م).

במילים אחרות... מימוש של std::facet גרוע, יש בעיות בייצוג locale באופן כללי.

עצוב שזה המצב בשנת 2009...

נפלאות ה־Comet בשרתי האינטרנט המודרניים...

ב־יום שישי, 28 באוגוסט 2009, מאת ארתיום; פורסם תחת: תכנה חופשית, אינטרנט, לינוקס, תכנה ומחשבים, CppCMS; ‏2 תגובות

כפי שפרסמתי לאחרונה, אני עובד על תמיכה ב־Comet או HTTP Push ב־CppCMS. כאשר הכוונה לאפשרות שרת האינטרנט ליידע את הלקוח על אירוע חדש, למשל: "הגיעה מסר מידי חדש, או מחיר המניה השתנה" -- למעשה להעביר אירועים ללקוח בזמן אמת.

כיצד התהליך מתבצע? הלקוח פונה לשרת עם בקשת HTTP לקבל עדכונים; והשרת, במקום לענות באופן מידי ממתין ומחזיק את הקשר פתוח. כאשר מגיע האירוע החדש, כמו עדכון מחיר המניה או הודעה חדש מחבר, התשובה נשלחת והתליך חוזר.

לא מי יודע מה מסובך כמובן זה גם תלוי ביכולת השרת להחזיק קשר HTTP פתוח למשך הרבה זמן.

אבל, מה קורה אם הלקוח סוגר את הקשר לפני שהוא מקבל תשובה? בבקשות HTTP רגילות זה אירוע נדיר והיישום בצד השרת יכול בקלות "להתעלם" ממצב כזה. ביישומי Comet זה שונה: מספיק שמישהו נכנס לאתר שמחכה לדף שמבצע בקשה מסוג זה ויוצא ממנו, הקשר לקבלת עדכונים ייסגר.

אבל מה יישום Comet אמור לעשות? תחשבו שמספר הבקשות HTTP שנסגרות לפני דיווח על אירוע מסוים יכול להיות הרבה יותר גדול ממספר התגובות הרלוונטיות בפועל. אז יישום תקין צריך לזהות ניתוקים כאלה, ולמחוק אותם מ"רשימת התפוצה שלו".

אבל מה? יישום ה־Comet בד"כ לא מדבר ישירות עם הלקוח בעזרת HTTP אלא מדבר עם שרת web בעזרת פרוטוקול סטנדרטי כמו FastCGI או SCGI. לכן, תפקידו של השרת הוא לדווח ליישום על כך שהלקוח סגר את הקשר. למעשה פרוטוקול FastCGI מגדיר במפורש דרך להפסיק בקשה מסויימת ע"י סגירת ה־socket או שליחת בקשה מיוחדת "Abord Request", כנ"ל ניתן לבצע בעזרת scgi ע"י ניתוק ה־socket.

פשוט? כן. האם זה קורה בפועל? לא ממש.

אחרי שמימשתי מערכת ניתוק הקשר ובדקתי אותה על שרת http פנימי, החלטתי לבדוק את ההתנהגות של שרתי web אמתיים: Lighttpd,‏ Nginx ו־Apache2. מה שגיליתי היה ממש לא נעים: למעט Nginx אף שרת לא מדווח על ניתוק הקשר לא מעל FastCGI ולא מעל SCGI.

לצורך דוגמה פשוטה, אני יצרתי חיבור ומיד סגרתי אותו, כך עשיתי עשר פעם.

  • Nginx הוא היחיד דיווח על כך ליישום FastCGI באופן מידי ואפשר לי לטפל בלקוח ש"נעלם"
  • Apache דיווח רק אחרי timeout ארוך של כדקה הן ב־FastCGI והן ב־SCGI.‏
  • lighttpd בכלל שכח מזה והחזיק קשרים פתוחים כל הזמן -- יותר מזה בירידה, הוא התלונן על כך שהיישום שלי "נעלם" ולא ענה לבקשת השרת (שאין לו כבר למי להעביר אותה).

בקיצור... זה היה מאוד מאכזב. אני הייתי מוכן לקבל את זה מ־Apache שידוע כשרת שלא נועד לטפל בהרבה קשרים פתוחים, אבל Lighty? פתחתי על זה באג.

מזל שמימשתי שרת HTTP פנימי בעצמי.

חדשות CppCMS...

ב־יום שלישי, 18 באוגוסט 2009, מאת ארתיום; פורסם תחת: תכנה חופשית, אינטרנט, לינוקס, פיתוח, תכנה ומחשבים, CppCMS, C++‎‏; ‏5 תגובות

לאחרונה אני עובד בענף ה־refactoring של CppCMS ומבצע שינויים גדולים. אביא כאן סקירה קצרה של השינוי שכבר נמצאות בגרסה ניסיונית:

  1. אחד השינויים הגדולים והחשובים זה להיפתר מכל התלויות המיותרות או מגבילות. אחרי שכל השינויים יסתיימו, התלויות היחידות שיישארו הן גרסה עדכנית של Boost ו־Python לצורכי הפיתוח בלבד.

    חלק מהספריות הוסרו בגלל אי תאימות לדרישות החדשות:

    • libfcgi ירד כי ה־API שלו לא מאפשר גישה א־סינכרונית, במקומו, מימשתי את הפרוטוקול בעצמי על בסיס Boost.Asio.
    • ספריית CgiCC ירדה בגלל האיכות הירודה שלה וחוסר יכולת סבירה לתקשר עם המפתח של אותה הספרייה הבעייתית.

    כך שבגרסה הבאה, תהיה לי אפשרות להכין debים ו־rpmים בקלות...

  2. עד היום, פיתוח מול CppCMS דרש שימוש בשרת חיצוני, למרות שיש לי סקריפט הפעלה אוטומטית של lighttpd, ‏nginx ו־Apache, עכשיו מימשתי שרתי HTTP פנימי פשוט שמקל על הפיתוח ובנוסף, עתיד יקל על שיבוץ התשתית ביישומים שדורשים ממשק web ובמערכות משובצות מחשב.

    כך שכיום, CppCMS החדש תומך בשלושה ממשקים FastCGI,‏ SCGI ו־HTTP.‏

  3. התווספה תמיכה מסודרת בלוקליזציה עם שימוש ב־std::locale, כך שתצוגת התאריכים, מספרים, מחרוזות וכד' יתבצעו בהתאם למקובל באותה שפה.

  4. בגלל שימוש מקיף ב־Boost -- ספריה בלתי תלויה בפלטפורמה, אני סוף־סוף אוכל להכריז על Windows כפלטפורמה שנתמכת באופן (חצי) רשמי.

יש עוד הרבה עבודת אינטגרציה של רכיבים שיצאו באופן זמני, כמו ניהול sessions, שינויים ב־cache, שכתוב תמיכה בטפסים ועוד.

אבל לאט־לאט ההשפעה של השינויים הארכיטקטוניים מתחילים להתבהר.

לתמוך או לא לתמוך, זאת השאלה (ב־Win32)?

ב־יום חמישי, 6 באוגוסט 2009, מאת ארתיום; פורסם תחת: תכנה חופשית, אינטרנט, לינוקס, פיתוח, תכנה ומחשבים, CppCMS, C++‎‏; ‏2 תגובות

כפי שפרסמתי בעבר, אני עובד על שינויים בפנימיים עמוקים ב־CppCMS שבין השאר יאפשרו:

  • תמיכה באירועי צד השרת או Comet.
  • תמיכה בבינאום ולורקליזציה.
  • תמיכה ב־ABI לאחור.
  • ניקיון יסודי של קוד תוך הקטנה משמעותית בשימוש בספריות צד ג'.

בגלל שאני עושה שינויים כל־כך מהותיים, חשבתי, אולי להוסיף גם תמיכה בעוד פלטפורמה בנוסף לתמיכה ב־Linux,‏ FreeBSD,‏ Solaris ו־Cygwin... להוסיף תמיכה ב־Windows.

זה באמת, לא אמור להיות עד כדי כך מסובך, יצא לי כבר פעם לבנות CppCMS עבור Mingw (כמובן נאלצתי לוותר על חלק גדול מהמודולים).

אבל, בין לבנות משהו שרץ עד לפלטפורמת פיתוח אמתית יש תהום.

המשך...

העמוד הבא

העמוד הבא

דפים

נושאים