Permission denied при удалении файла

Страницы: 1
RSS
Permission denied при удалении файла
 
Скрипт не может удалить закрытый файл.
Код:
Код
function main()
  local filename = "file.txt"
  local f = assert(io.open(filename, "w"))
  os.execute("start cmd.exe")
  message(tostring(f:close()) .. "\n" .. tostring(f))
  assert(os.remove(filename))  -- file.txt: Permission denied
end
Если поместить вызов os.execute() после закрытия файла, то удаляется.
 
Цитата
Незнайка написал:
Если поместить вызов os.execute() после закрытия файла, то удаляется
Все правильно, если файл открыт вы его не удалите. Попробуйте открыть файл и потом попробовать удалить файл через графический интерфейс windows.
Q
 
Цитата
QApplication написал:
если файл открыт

f:close() закрывает файл
os.remove() - удаление файла файла
 
Перед вызовом os.remove() файл закрыт, о чем указывается в окне сообщений:
Цитата
true
file (closed)
 
Какой ещё хернёй этот форум не загажен?

Незнайка, Вам нужно удалить файл? Так используйте, блин, ту последовательность, которая работает! Тем более, что Вы её знаете.
 
Цитата
Незнайка написал:
Перед вызовом os.remove() файл закрыт
Закрыт этот хэндл в этом приложении. Если файл не удаляется, значит, есть другой хэндл где-то еще. В os.execute точно эта самая команда, что приведена, или все же там запускается нечто, что этот файл читает?  Во втором случае надо запускать читающее приложение без start, тогда execute дождется его завершения.
 
Цитата
Anton написал:
В os.execute точно эта самая команда, что приведена
Код, на котором наблюдается проблема, приведен полностью. Его можно запустить и убедиться в этом.
 
Цитата
Незнайка написал:
можно запустить
Мне сейчас не на чем. Тем не менее, раз код именно таков, остается одно предположение: хэндл файла наследуется запускаемым процессом и удерживается открытым до его завершения, что и не дает удалить файл. Решение - закрывайте файл перед запуском процесса, удаляйте после. Если предположение верно, все заработает, и тогда это будет не косяк арки и даже не косяк луа, это будет косяк майкрософтовского си-рантайма.
 
Что характерно, на standalone lua то же самое и без os.execute то же самое.

Похоже что луа хендл не закрывает по fclose, а ставит флажок. Она не по  fopen и fclose работает.
 
Цитата
s_mike@rambler.ru написал:
Похоже что луа хендл не закрывает по fclose, а ставит флажок.
Файл закрывается так (луа 5.3)
Код
static int aux_close (lua_State *L) {
  LStream *p = tolstream(L);
  volatile lua_CFunction cf = p->closef;
  p->closef = NULL;  /* mark stream as closed */
  return (*cf)(L);  /* close it */
}

static int f_close (lua_State *L) {
  tofile(L);  /* make sure argument is an open stream */
  return aux_close(L);
}
При открытии файла closef устанавливается на функцию
Код
static int io_fclose (lua_State *L) {
  LStream *p = tolstream(L);
  int res = fclose(p->f);
  return luaL_fileresult(L, (res == 0), NULL);
}
Так что закрывает как положено. Другое дело, если явно не закрыть, тогда эта функция отработает только при сборке объекта файла, т.е. когда рак на горе свистнет.
 
Цитата
s_mike@rambler.ru написал:
и без os.execute то же самое
Без os.execute() файл удаляется.

Цитата
Anton написал:
хэндл файла наследуется запускаемым процессом и удерживается открытым до его завершения
Похоже, так и есть, запускаемый процесс удерживает все открытые (на момент его запуска) файлы до своего завершения.
 
Цитата
Незнайка написал:
Цитата
s_mike@rambler.ru написал:
и без os.execute то же самое
Без os.execute() файл удаляется.

Цитата
Anton написал:
хэндл файла наследуется запускаемым процессом и удерживается открытым до его завершения
Похоже, так и есть, запускаемый процесс удерживает все открытые (на момент его запуска) файлы до своего завершения.
легко проверить.

сделайте между запуском oos.execute и os. remove паузу, достаточную чтобы руками закрыть созданное окно шелла
 
Цитата
Anton написал:
Цитата
   s_mike@rambler.ru написал:
Похоже что луа хендл не закрывает по fclose, а ставит флажок.
Файл закрывается так (луа 5.3)
Код
  static int aux_close (lua_State  * L) {
  LStream  * p  =  tolstream(L);
  volatile lua_CFunction cf  =  p -  > closef;
  p -  > closef  =  NULL;  / *  mark stream as closed  * /
   return  ( * cf)(L);  / *  close it  * /
}

static int f_close (lua_State  * L) {
  tofile(L);  / *  make sure argument is an open stream  * /
   return  aux_close(L);
}  
При открытии файла closef устанавливается на функцию
Код
  static int io_fclose (lua_State  * L) {
  LStream  * p  =  tolstream(L);
  int res  =  fclose(p -  > f);
   return  luaL_fileresult(L, (res  =  =   0 ), NULL);
}  
Так что закрывает как положено. Другое дело, если явно не закрыть, тогда эта функция отработает только при сборке объекта файла, т.е. когда рак на горе свистнет.
Я пробовал вставлять до os.remove collectgarbage("collect") - рез
 
ультат тот же. пробовал на стандалоне
 
Цитата
s_mike@rambler.ru написал:
Я пробовал вставлять до os.remove collectgarbage("collect")
Надеюсь, f = nil; collectgarbage("collect"), а то ж объект еще не вышел из скоупа.
 
Цитата
s_mike@rambler.ru написал:
Цитата
Незнайка написал:
Цитата
Anton  написал:
хэндл файла наследуется запускаемым процессом и удерживается открытым до его завершения
Похоже, так и есть, запускаемый процесс удерживает все открытые (на момент его запуска) файлы до своего завершения.
легко проверить.
сделайте между запуском oos.execute и os. remove паузу, достаточную чтобы руками закрыть созданное окно шелла

Подтверждается.
Как и то, что, даже если сам скрипт завершится раньше, то файл останется заблокированным до закрытия шелла.
 
Если из запущенного процесса запустить другой(ие) процесс(ы), то файл останется заблокированным, пока не закроешь всю ветвь.
 
Цитата
Anton написал:
Цитата
   s_mike@rambler.ru написал:
Я пробовал вставлять до os.remove collectgarbage("collect")
Надеюсь, f = nil; collectgarbage("collect"), а то ж объект еще не вышел из скоупа.
да, именно так.

но с Незнайкой у нас получились разные результаты .
 
Цитата
s_mike@rambler.ru написал:
но с Незнайкой у нас получились разные результаты
И со мной теперь тоже разные. Есть у меня хост самопальный с луа 5.3 (не тот, что с луа идет), в нем все как описано, с execute файл не удаляется, без execute удаляется. Более того, если после ошибки попробовать удалить файл руками, винда говорит, что он открыт в интерпретаторе команд, после закрытия консоли повторная попытка файл удаляет. Таким образом, версия с наследованием хэндла подтверждена. А вот ваш случай удивляет. По-любому лишний хэндл есть, только где. Какой-нибудь антивирус все новые файлы смотрит? Какой-нибудь архиватор? Какая-нибудь фича винды активна? Какой-нибудь вирус сидит? Не угадать.
Страницы: 1
Читают тему (гостей: 1)
Наверх