1. PHP / Говнокод #23940

    −1

    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
    public function syncStock() {
            $locked = file_exists(__DIR__ . '/lock/gk_sync_stock');
    
            if ($locked) {
                $this->logger->log("Attempt to sync locked stock");
                return;
            }
    
            file_put_contents(__DIR__ . '/lock/gk_sync_stock', current_time('mysql'));
    
            $changed = $this->_syncStock();
    
            unlink(__DIR__ . '/lock/gk_sync_stock');
    
            $this->logger->log("Sync stock complete, $changed changed");
        }

    Тут может произойти дедлок, или ни один из синхронных запросов не выполнится?

    Запостил: inho, 16 Марта 2018

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

    • #SEO PHP - синхронизация потоков для людей
      Ответить
      • >>>"синхронных запросов"

        Почему-то сразу вспомнились два камерунских члена, пытавшихся одновременно проникнуть в анус SemaReal'а (этакий "Twix").
        Ответить
        • У меня тоже бывают пищевые ассоциации. Скажем, когда твоя мамка брала в рот и зад однлвременно, она была похожа на хрюшку на вертеле
          Ответить
    • Тут у тебя гонка получится, если 2 потока одновременно пройдут тест в строке 4.
      Ответить
    • >>синхронизация
      >>php
      тили-тили
      трали-вали
      а мы flock() не проходили
      а нам flock() не задавали
      чирик
      пиздых
      хуяк
      куку http://php.net/manual/ru/function.flock.php
      Ответить
      • Знал же про них, лень было использовать :D
        Ответить
      • public function syncStock() {
            $lock_path = __DIR__ . '/lock/gk_sync_stock.lock';
        
            if (SyncLockHelper::skipIfLocked($lock_path)) {
                $this->logger->log("Attempt to sync locked stock");
                return null;
            }
        
            $changed = $this->_syncStock();
        
            unlink($lock_path);
        
            $this->logger->log("Sync stock complete, $changed changed");
        }
        
        class SyncLockHelper {
            /**
             * @param string $lock_path lockfile path
             *
             * @return int 1 if need to slip this action because of lock, 0 otherwise
             */
            public static function skipIfLocked($lock_path) {
                $fp = fopen($lock_path, 'a+');
        
                if (!$fp) {
                    return 1;
                }
        
                $return = 0;
        
                if (flock($fp, LOCK_EX)) {
                    $size = filesize($lock_path);
        
                    if ($size > 0) { // check is file exists and not empty
                        $return = 1;
                    } else {
                        ftruncate($fp, 0);
                        fwrite($fp, current_time('mysql'));
                        fflush($fp);
                    }
        
                    flock($fp, LOCK_UN);
                } else {
                    // SOME ERROR
                    return 1;
                }
        
                fclose($fp);
        
                return $return;
            }
        }


        А так?
        Ответить
        • Не оч понятно что ты делаешь, и зачем.

          Да, два процесса не смогу зайти за flock, и пока ты write никто не сможет его truncate.
          Но вот зачем тут целый класс, какая логика стоит за возвращаемым значением и что делает _syncStock я не знаю
          Ответить
          • Походу он пытается присунуть синхронизацию стока в обработку запросов от юзеров. Пыхоархитектура.
            Ответить
            • Не совсем так. Если засунуть в обработку запроса, то запрос юзера будет тормозить. Поэтому там отсылается отдельный запрос асинхронно по расписанию. Если на сайт пришло 2 запроса в час, то будут 2 попытки синхронизации следом за этими запросами. Если пришло 100500 запросов, то синронизации будут каждые 30 секунд. Это wp-cron.
              Ответить
          • Если 1 процесс уже зашел, то второй зашедший должен быть отброшен. Как это написать проще я не знаю.
            Ответить
      • Пожалуй, лучше всего о "качестве" "PHP" говорят комментарии к его официальной документации:
        The supplied documentation is vague, ambiguous and lacking, and the user comments contain erroneous information! [...]
        Ответить
    • В питоне с wsgi это в принципе возможно?
      Ответить
      • Порвал твоего питона надвое, проверь.
        Ответить
      • что именно? Параллельная обработка двух запросов? Вполне возможна.

        Дедлока не будет так как никто никого не ждет, а вот гонка тоже может быть
        Ответить
        • Питон же в одном треде и в одном процессе работает, нет?
          Ответить
          • Х.з., у меня uwsgi джва воркера крутит в разных процессах.
            Ответить
            • А зачем? Таки код напитоне как крутится? В двух тредах? В двух процессах? Хз.
              Ответить
              • В двух процессах, в каждом свой питон. Можно ещё добавить в настройках если больше параллельности надо.

                В общем-то uwsgi и треды (обычные и зелёные) должен уметь, но я не стал с ними заморачиваться (в прошлый раз они только на втором питоне работали).
                Ответить
              • Питону, как языку, пофиг как крутится твой код.
                Ну вот например гуникорн умеет обычный prefork (когда он родит несколько процессов и каждый обслуживает клиента) и стопицот вариантов async.

                Почитай, тут все написано:
                http://docs.gunicorn.org/en/stable/design.html

                Конкретно этот код шарит не объект в адресном пространстве, а в внешний файл, так что даже два питона могут его одновременно обрабаывать.
                Ответить
                • > внешний файл
                  А если питоны на разных машинах, то достаточно положить этот файл на шару.
                  Ответить
                • >Питону, как языку, пофиг как крутится твой код.
                  Очень ценное замечание. Программисту только не пофиг.

                  >этот код шарит в внешний файл
                  Это как?
                  Ответить
                  • Ты сказал: "Питон же в одном треде и в одном процессе работает, нет?".
                    Эта фраза звучит так, словно бы ЯП Python требует всегда наличие одного процесса и одного потока. Ну вот я тебя поправил: это не так.
                    Ответить
                  • >>этот код шарит в внешний файл
                    >Это как?

                    Ну ты читал код топикстартера? Он пытается синхронизироваться по файлу. То-есть даже два отдельно запущенных питона будут этой синхронизации подвержены.
                    Ответить

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