Help us understand the problem. What is going on with this article?

Goのos.RenameはLinuxではちゃんとrename(2)を使っているのか

More than 5 years have passed since last update.

それはまあ、そうだろうとは思うのだが、本当にそうか(すなわちアトミックにファイル操作するのか)を確認した。

renamer.go
package main

import "os"

func main() {
    dest := os.Args[1]
    src := os.Args[2]

    if e := os.Rename(dest, src); e != nil {
        panic(e)
    }
}

こういうなんてことの無いプログラムをビルドし、手頃なLinux amd64のVMで strace を走らせる。

[vagrant@www tmp]$ strace ./renamer sample sample.1
execve("./renamer", ["./renamer", "sample", "sample.1"], [/* 22 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x4bcb30)       = 0
sched_getaffinity(0, 128, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) = 128
mmap(0xc000000000, 65536, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xc000000000
munmap(0xc000000000, 65536)             = 0
mmap(NULL, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff4f672d000
mmap(0xc208000000, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xc208000000
mmap(0xc207ff0000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xc207ff0000
mmap(0xc000000000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xc000000000
mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff4f671d000
mmap(NULL, 1439992, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff4f65bd000
sigaltstack({ss_sp=0xc208002000, ss_flags=0, ss_size=32768}, NULL) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigaction(SIGHUP, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGHUP, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGINT, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGILL, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGTRAP, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGABRT, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGBUS, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGFPE, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGUSR1, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGSEGV, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
...
rt_sigaction(SIGRT_21, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGRT_22, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGRT_23, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGRT_24, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGRT_25, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGRT_26, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGRT_27, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGRT_28, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGRT_29, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGRT_30, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGRT_31, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigaction(SIGRT_32, {0x434000, ~[], SA_RESTORER|SA_STACK|SA_RESTART|SA_SIGINFO, 0x434070}, NULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, ~[], [], 8) = 0
clone(child_stack=0xc208030000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD) = 1222
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
futex(0x4b5960, FUTEX_WAKE, 1)          = 1
rt_sigprocmask(SIG_SETMASK, ~[], [], 8) = 0
clone(child_stack=0xc20802e000, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD) = 1223
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
futex(0x4b5e18, FUTEX_WAIT, 0, NULL)    = 0
rename("sample", "sample.1")            = 0
futex(0x4b5960, FUTEX_WAKE, 1)          = 1
exit_group(0)                           = ?
+++ exited with 0 +++

rename(2) 呼んでました。こちらからは以上です。

追記

社のチャットで実際どう言うコードなのよ?という話をしたら大変勉強になりました...

udzura
投稿しているコードは、指定が無い限り MIT とします。
http://udzura.hatenablog.jp
pepabo
「いるだけで成長できる環境」を標榜し、エンジニアが楽しく開発できるWebサービス企業を目指しています。
https://pepabo.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away