diff --git a/.gitignore b/.gitignore index da5bf8e6c8..fe7281c2cc 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ /.user.bazelrc /bazel-* /urbit +MODULE.bazel +MODULE.bazel.lock # Swap files. *.swo diff --git a/INSTALL.md b/INSTALL.md index 5f55e076a9..df92060dfb 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -161,6 +161,13 @@ doesn't match the version of `clang` installed on your system. To address this, run `clang --version` and pass the version number via `--clang_version=""` to the failing command. +If build fails on nix/NixOS, you should pass `ACLOCAL_PATH` environment +variable to bazel, using `--action_env=ACLOCAL_PATH=$ACLOCAL_PATH`, like so: + +``` +bazel build :urbit --action_env=ACLOCAL_PATH=$ACLOCAL_PATH +``` + [^1]: If you're interested in digging into the details of the build system, check out [`WORKSPACE.bazel`](WORKSPACE.bazel), [`BUILD.bazel`](BUILD.bazel), [`bazel/`](bazel), and the multiple diff --git a/VERSION b/VERSION index 9f55b2ccb5..8c50098d8a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0 +3.1 diff --git a/WORKSPACE.bazel b/WORKSPACE.bazel index dca6750619..6661562bee 100644 --- a/WORKSPACE.bazel +++ b/WORKSPACE.bazel @@ -222,7 +222,7 @@ versioned_http_archive( build_file = "//bazel/third_party/natpmp:natpmp.BUILD", sha256 = "0684ed2c8406437e7519a1bd20ea83780db871b3a3a5d752311ba3e889dbfc70", strip_prefix = "libnatpmp-{version}", - url = "http://miniupnp.free.fr/files/libnatpmp-{version}.tar.gz", + url = "http://download.openpkg.org/components/cache/libnatpmp/libnatpmp-{version}.tar.gz", version = "20230423", ) @@ -264,7 +264,7 @@ versioned_http_archive( build_file = "//bazel/third_party/openssl:openssl.BUILD", sha256 = "cf3098950cb4d853ad95c0841f1f9c6d3dc102dccfcacd521d93925208b76ac8", strip_prefix = "openssl-{version}", - url = "https://www.openssl.org/source/openssl-{version}.tar.gz", + url = "https://github.com/openssl/openssl/releases/download/OpenSSL_1_1_1w/openssl-{version}.tar.gz", version = "1.1.1w", ) diff --git a/bazel/third_party/avahi/avahi.BUILD b/bazel/third_party/avahi/avahi.BUILD index 84d27171c2..2c0896f32d 100644 --- a/bazel/third_party/avahi/avahi.BUILD +++ b/bazel/third_party/avahi/avahi.BUILD @@ -17,7 +17,7 @@ configure_make( "@platforms//os:macos": ["--jobs=`sysctl -n hw.logicalcpu`"], "//conditions:default": ["--jobs=`nproc`"], }), - configure_options = ["--with-dbus-system-address='unix:path=/var/run/dbus/system_bus_socket' --with-xml=none --disable-libevent --disable-glib --disable-gobject --disable-gdbm --disable-qt3 --disable-qt4 --disable-qt5 --disable-gtk --disable-gtk3 --disable-mono --disable-monodoc --disable-python --disable-libdaemon --enable-compat-libdns_sd --disable-rpath"], + configure_options = ["--with-dbus-system-address='unix:path=/var/run/dbus/system_bus_socket' --with-xml=none --disable-libevent --disable-glib --disable-gobject --disable-gdbm --disable-qt3 --disable-qt4 --disable-qt5 --disable-gtk --disable-gtk3 --disable-mono --disable-monodoc --disable-python --disable-libdaemon --enable-compat-libdns_sd --disable-rpath --with-distro=none"], lib_source = ":all", # out_include_dir = "avahi-compat-libdns_sd", deps = ["@dbus"], diff --git a/flake.lock b/flake.lock index e0fc6ef9a4..10f88e0e43 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1701626906, - "narHash": "sha256-ugr1QyzzwNk505ICE4VMQzonHQ9QS5W33xF2FXzFQ00=", + "lastModified": 1712849433, + "narHash": "sha256-flQtf/ZPJgkLY/So3Fd+dGilw2DKIsiwgMEn7BbBHL0=", "owner": "nixos", "repo": "nixpkgs", - "rev": "0c6d8c783336a59f4c59d4a6daed6ab269c4b361", + "rev": "f173d0881eff3b21ebb29a2ef8bedbc106c86ea5", "type": "github" }, "original": { @@ -23,11 +23,11 @@ ] }, "locked": { - "lastModified": 1701473968, - "narHash": "sha256-YcVE5emp1qQ8ieHUnxt1wCZCC3ZfAS+SRRWZ2TMda7E=", + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "34fed993f1674c8d06d58b37ce1e0fe5eebcb9f5", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 336f0f3ba2..05237289b3 100644 --- a/flake.nix +++ b/flake.nix @@ -104,12 +104,16 @@ ] ++ (with pkgs; [ autoconf + autoconf-archive automake - bazel_5 + bazel_6 binutils # for `nm` jdk11_headless libtool m4 + pkg-config + git + perl ]); extraBuildCommands = '' chmod +w usr diff --git a/pkg/noun/events.c b/pkg/noun/events.c index 6e82a87146..d4b556aae8 100644 --- a/pkg/noun/events.c +++ b/pkg/noun/events.c @@ -324,9 +324,15 @@ u3e_fault(u3_post low_p, u3_post hig_p, u3_post off_p) return u3e_flaw_good; } +typedef enum { + _ce_img_good = 0, + _ce_img_fail = 1, + _ce_img_size = 2 +} _ce_img_stat; + /* _ce_image_stat(): measure image. */ -static c3_o +static _ce_img_stat _ce_image_stat(u3e_image* img_u, c3_w* pgs_w) { struct stat buf_u; @@ -334,7 +340,7 @@ _ce_image_stat(u3e_image* img_u, c3_w* pgs_w) if ( -1 == fstat(img_u->fid_i, &buf_u) ) { fprintf(stderr, "loom: stat %s: %s\r\n", img_u->nam_c, strerror(errno)); u3_assert(0); - return c3n; + return _ce_img_fail; } else { c3_z siz_z = buf_u.st_size; @@ -342,19 +348,19 @@ _ce_image_stat(u3e_image* img_u, c3_w* pgs_w) if ( !siz_z ) { *pgs_w = 0; - return c3y; + return _ce_img_good; } else if ( siz_z != _ce_len(pgs_z) ) { fprintf(stderr, "loom: %s corrupt size %zu\r\n", img_u->nam_c, siz_z); - return c3n; + return _ce_img_size; } else if ( pgs_z > UINT32_MAX ) { fprintf(stderr, "loom: %s overflow %zu\r\n", img_u->nam_c, siz_z); - return c3n; + return _ce_img_fail; } else { *pgs_w = (c3_w)pgs_z; - return c3y; + return _ce_img_good; } } } @@ -397,7 +403,7 @@ _ce_ephemeral_open(c3_i* eph_i) /* _ce_image_open(): open or create image. */ -static c3_o +static _ce_img_stat _ce_image_open(u3e_image* img_u, c3_c* ful_c) { c3_i mod_i = O_RDWR | O_CREAT; @@ -406,14 +412,10 @@ _ce_image_open(u3e_image* img_u, c3_c* ful_c) snprintf(pax_c, 8192, "%s/%s.bin", ful_c, img_u->nam_c); if ( -1 == (img_u->fid_i = c3_open(pax_c, mod_i, 0666)) ) { fprintf(stderr, "loom: c3_open %s: %s\r\n", pax_c, strerror(errno)); - return c3n; - } - else if ( c3n == _ce_image_stat(img_u, &img_u->pgs_w) ) { - return c3n; - } - else { - return c3y; + return _ce_img_fail; } + + return _ce_image_stat(img_u, &img_u->pgs_w); } /* _ce_patch_write_control(): write control block file. @@ -1371,13 +1373,18 @@ u3e_backup(c3_c* pux_c, c3_c* pax_c, c3_o ovw_o) // c3_c nux_c[8193]; snprintf(nux_c, 8192, "%s/%s.bin", pux_c, nux_u.nam_c); - if ( (0 != access(nux_c, F_OK)) || (c3n == _ce_image_open(&nux_u, pux_c)) ) { + if ( (0 != access(nux_c, F_OK)) + || (_ce_img_good != _ce_image_open(&nux_u, pux_c)) ) + { fprintf(stderr, "loom: couldn't open north image at %s\r\n", pux_c); return c3n; } + c3_c sux_c[8193]; snprintf(sux_c, 8192, "%s/%s.bin", pux_c, sux_u.nam_c); - if ( (0 != access(sux_c, F_OK)) || (c3n == _ce_image_open(&sux_u, pux_c)) ) { + if ( (0 != access(sux_c, F_OK)) + || (_ce_img_good != _ce_image_open(&sux_u, pux_c)) ) + { fprintf(stderr, "loom: couldn't open south image at %s\r\n", pux_c); return c3n; } @@ -1487,9 +1494,9 @@ u3e_save(u3_post low_p, u3_post hig_p) #ifdef U3_SNAPSHOT_VALIDATION { c3_w pgs_w; - u3_assert( c3y == _ce_image_stat(&u3P.nor_u, &pgs_w) ); + u3_assert( _ce_img_good == _ce_image_stat(&u3P.nor_u, &pgs_w) ); u3_assert( pgs_w == u3P.nor_u.pgs_w ); - u3_assert( c3y == _ce_image_stat(&u3P.sou_u, &pgs_w) ); + u3_assert( _ce_img_good == _ce_image_stat(&u3P.sou_u, &pgs_w) ); u3_assert( pgs_w == u3P.sou_u.pgs_w ); } #endif @@ -1590,9 +1597,11 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) // c3_c chk_c[8193]; snprintf(chk_c, 8193, "%s/.urb/chk", u3P.dir_c); - if ( (c3n == _ce_image_open(&u3P.nor_u, chk_c)) || - (c3n == _ce_image_open(&u3P.sou_u, chk_c)) ) - { + + _ce_img_stat nor_e = _ce_image_open(&u3P.nor_u, chk_c); + _ce_img_stat sou_e = _ce_image_open(&u3P.sou_u, chk_c); + + if ( (_ce_img_fail == nor_e) || (_ce_img_fail == sou_e) ) { fprintf(stderr, "boot: image failed\r\n"); exit(1); } @@ -1609,6 +1618,10 @@ u3e_live(c3_o nuu_o, c3_c* dir_c) _ce_patch_free(pat_u); _ce_patch_delete(); } + else if ( (_ce_img_size == nor_e) || (_ce_img_size == sou_e) ) { + fprintf(stderr, "boot: image failed (size)\r\n"); + exit(1); + } nor_w = u3P.nor_u.pgs_w; sou_w = u3P.sou_u.pgs_w; diff --git a/pkg/noun/manage.c b/pkg/noun/manage.c index d880a42032..71d673e357 100644 --- a/pkg/noun/manage.c +++ b/pkg/noun/manage.c @@ -2065,7 +2065,7 @@ u3m_init(size_t len_i) -1, 0); u3l_log("boot: mapping %zuMB failed", len_i >> 20); - u3l_log("see urbit.org/using/install/#about-swap-space" + u3l_log("see https://docs.urbit.org/manual/getting-started/self-hosted/cloud-hosting" " for adding swap space"); if ( -1 != (c3_ps)map_v ) { u3l_log("if porting to a new platform, try U3_OS_LoomBase %p", diff --git a/pkg/vere/disk.c b/pkg/vere/disk.c index 58cb2f822f..1a55abbef8 100644 --- a/pkg/vere/disk.c +++ b/pkg/vere/disk.c @@ -1123,18 +1123,39 @@ u3_disk_epoc_zero(u3_disk* log_u) } // create epoch version file, overwriting any existing file + c3_c epi_c[8193]; c3_c epv_c[8193]; + snprintf(epi_c, sizeof(epv_c), "%s/epoc.tmp", epo_c); snprintf(epv_c, sizeof(epv_c), "%s/epoc.txt", epo_c); - FILE* epv_f = fopen(epv_c, "w"); // XX errors - fprintf(epv_f, "%d", U3E_VERLAT); - fclose(epv_f); + FILE* epv_f = fopen(epi_c, "w"); // XX errors + + if ( !epv_f + || (0 > fprintf(epv_f, "%d", U3E_VERLAT)) + || fflush(epv_f) + || (-1 == c3_sync(fileno(epv_f))) + || fclose(epv_f) + || (-1 == rename(epi_c, epv_c)) ) + { + fprintf(stderr, "disk: write epoc.txt failed %s\r\n", strerror(errno)); + goto fail3; + } // create binary version file, overwriting any existing file + c3_c bii_c[8193]; c3_c biv_c[8193]; - snprintf(biv_c, sizeof(biv_c), "%s/vere.txt", epo_c); - FILE* biv_f = fopen(biv_c, "w"); // XX errors - fprintf(biv_f, URBIT_VERSION); // XX append a sentinel for auto-rollover? - fclose(biv_f); + snprintf(bii_c, sizeof(biv_c), "%s/vere.tmp", epo_c); + snprintf(biv_c, sizeof(epv_c), "%s/vere.txt", epo_c); + FILE* biv_f = fopen(bii_c, "w"); + if ( !biv_f + || (0 > fprintf(biv_f, URBIT_VERSION)) + || fflush(biv_f) + || (-1 == c3_sync(fileno(biv_f))) + || fclose(biv_f) + || (-1 == rename(bii_c, biv_c)) ) + { + fprintf(stderr, "disk: write vere.txt failed %s\r\n", strerror(errno)); + goto fail3; + } if ( -1 == c3_sync(epo_i) ) { // XX fdatasync on linux? fprintf(stderr, "disk: sync epoch dir 0i0 failed: %s\r\n", strerror(errno)); @@ -1205,18 +1226,44 @@ _disk_epoc_roll(u3_disk* log_u, c3_d epo_d) } // create epoch version file, overwriting any existing file + c3_c epi_c[8193]; c3_c epv_c[8193]; + snprintf(epi_c, sizeof(epv_c), "%s/epoc.tmp", epo_c); snprintf(epv_c, sizeof(epv_c), "%s/epoc.txt", epo_c); - FILE* epv_f = fopen(epv_c, "w"); // XX errors - fprintf(epv_f, "%d", U3E_VERLAT); - fclose(epv_f); + FILE* epv_f = fopen(epi_c, "w"); + + if ( !epv_f + || (0 > fprintf(epv_f, "%d", U3E_VERLAT)) + || fflush(epv_f) + || (-1 == c3_sync(fileno(epv_f))) + || fclose(epv_f) + || (-1 == rename(epi_c, epv_c)) ) + { + fprintf(stderr, "disk: write epoc.txt failed %s\r\n", strerror(errno)); + goto fail3; + } // create binary version file, overwriting any existing file + c3_c bii_c[8193]; c3_c biv_c[8193]; - snprintf(biv_c, sizeof(biv_c), "%s/vere.txt", epo_c); - FILE* biv_f = fopen(biv_c, "w"); // XX errors - fprintf(biv_f, URBIT_VERSION); - fclose(biv_f); + snprintf(bii_c, sizeof(biv_c), "%s/vere.tmp", epo_c); + snprintf(biv_c, sizeof(epv_c), "%s/vere.txt", epo_c); + FILE* biv_f = fopen(bii_c, "w"); + if ( !biv_f + || (0 > fprintf(biv_f, URBIT_VERSION)) + || fflush(biv_f) + || (-1 == c3_sync(fileno(biv_f))) + || fclose(biv_f) + || (-1 == rename(bii_c, biv_c)) ) + { + fprintf(stderr, "disk: write vere.txt failed %s\r\n", strerror(errno)); + goto fail3; + } + + if ( -1 == c3_sync(epo_i) ) { // XX fdatasync on linux? + fprintf(stderr, "disk: sync epoch dir 0i0 failed: %s\r\n", strerror(errno)); + goto fail3; + } // get metadata from old log c3_d who_d[2]; @@ -1707,9 +1754,9 @@ _disk_epoc_load(u3_disk* log_u, c3_d lat_d) return _epoc_gone; } - if ( (1 != sscanf(ver_c, "%" SCNu32 "%n", &ver_w, &car_i)) - && (0 < car_i) - && ('\0' == *(ver_c + car_i)) ) + if ( !( (1 == sscanf(ver_c, "%" SCNu32 "%n", &ver_w, &car_i)) + && (0 < car_i) + && ('\0' == *(ver_c + car_i)) ) ) { fprintf(stderr, "disk: failed to parse epoch version: '%s'\r\n", ver_c); return _epoc_fail; diff --git a/pkg/vere/main.c b/pkg/vere/main.c index 361f8ad304..12c64d8ecd 100644 --- a/pkg/vere/main.c +++ b/pkg/vere/main.c @@ -936,6 +936,14 @@ report(void) LIBCURL_VERSION_PATCH); } +/* _stop_exit_fore(): exit before. +*/ +static void +_stop_exit_fore(c3_i int_i) +{ + kill(getpid(), SIGTERM); +} + /* _stop_exit(): exit immediately. */ static void @@ -2302,10 +2310,7 @@ _cw_play_snap(u3_disk* log_u) static void _cw_play_exit(c3_i int_i) { - // explicit fprintf to avoid allocation in u3l_log - // - fprintf(stderr, "\r\n[received keyboard stop signal, exiting]\r\n"); - raise(SIGINT); + kill(getpid(), SIGINT); } /* _cw_play_impl(): replay events, but better. @@ -2382,21 +2387,45 @@ _cw_play_impl(c3_d eve_d, c3_d sap_d, c3_o mel_o, c3_o sof_o, c3_o ful_o) */ static void* _cw_play_fork_heed(void* arg) { + // XX c3_c buf[1]; c3_zs red; + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + sigaddset(&set, SIGTSTP); + if ( 0 != pthread_sigmask(SIG_BLOCK, &set, NULL) ) { + fprintf(stderr, "play: watcher failed to block sigs: %s\r\n", strerror(errno)); + exit(1); + } + do { pthread_testcancel(); red = read(STDIN_FILENO, buf, sizeof(buf)); if ( 0 == red ) { fprintf(stderr, "play: god save the king! committing sudoku...\r\n"); - exit(1); + kill(getpid(), SIGINT); + return NULL; } } while ( 0 < red ); return NULL; } +/* _cw_play_fork_exit(): exit callback for uv_spawn. +*/ +void +_cw_play_fork_exit(uv_process_t* req_u, c3_ds sat_d, c3_i tem_i) { + if ( sat_d || tem_i ) { + fprintf(stderr, "play: failed: %" PRId64 " signal: %d\r\n", sat_d, tem_i); + exit(1); + } + uv_close((uv_handle_t*)req_u, NULL); +} + /* _cw_play_fork(): spawn a subprocess for event replay. */ static c3_i @@ -2451,56 +2480,37 @@ _cw_play_fork(c3_d eve_d, c3_d sap_d, c3_o mel_o, c3_o sof_o, c3_o ful_o) u3_assert( i_z < sizeof(argv) ); } - // prepare a pipe for ipc with the subprocess + // use uv_spawn to fork a new serf process and call its play subcommand // - c3_i pipefd[2]; - if ( 0 != pipe(pipefd) ) { - fprintf(stderr, "play: failed to open pipe\r\n"); - return 1; - } + u3L = uv_default_loop(); - // set the child process' stdin to read from the pipe - // - posix_spawn_file_actions_t action; - posix_spawn_file_actions_init(&action); - posix_spawn_file_actions_addclose(&action, pipefd[1]); - posix_spawn_file_actions_adddup2(&action, pipefd[0], STDIN_FILENO); + uv_pipe_t stdin_pipe; + uv_pipe_init(u3L, &stdin_pipe, 0); - // spawn a new serf process and call its play subcommand - // - pid_t pid_i; - c3_i sat_i; - if ( 0 != (sat_i = posix_spawn(&pid_i, u3_Host.wrk_c, &action, 0, argv, 0)) ) { - fprintf(stderr, "play: posix_spawn: %s\r\n", strerror(sat_i)); - return 1; - } - - // close the read end of the pipe in the parent - // - close(pipefd[0]); + uv_process_t child_req = {0}; + uv_process_options_t options = {0}; + uv_stdio_container_t stdio[3]; + stdio[0].data.stream = (uv_stream_t*) &stdin_pipe; + stdio[1].data.fd = STDOUT_FILENO; + stdio[2].data.fd = STDERR_FILENO; + stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE; // stdin + stdio[1].flags = UV_INHERIT_FD; // stdout + stdio[2].flags = UV_INHERIT_FD; // stderr + options.stdio_count = 3; + options.stdio = stdio; + options.file = argv[0]; + options.args = argv; + options.exit_cb = (uv_exit_cb)_cw_play_fork_exit; - // wait for the child to exit - // - if ( -1 == waitpid(pid_i, &sat_i, 0) ) { - fprintf(stderr, "play: waitpid: %s\r\n", strerror(errno)); + c3_i sat_i; + if ( 0 != (sat_i = uv_spawn(u3L, &child_req, &options)) ) { + fprintf(stderr, "play: uv_spawn: %s\r\n", uv_strerror(sat_i)); return 1; } - if ( WIFEXITED(sat_i) ) { - ret_i = WEXITSTATUS(sat_i); - if ( 0 != ret_i ) { - fprintf(stderr, "play: exited with %d\r\n", ret_i); - } - return ret_i; - } - else if ( WIFSIGNALED(sat_i) ) { - fprintf(stderr, "play: terminated by signal %d\r\n", WTERMSIG(sat_i)); - return 1; - } - else { - fprintf(stderr, "play: strange termination\r\n"); - return 1; - } + signal(SIGINT, SIG_IGN); + + return uv_run(u3L, UV_RUN_DEFAULT); } /* _cw_play(): replay events, but better. @@ -3224,7 +3234,7 @@ main(c3_i argc, // // Configured here using signal() so as to be immediately available. // - signal(SIGTSTP, _stop_exit); + signal(SIGTSTP, _stop_exit_fore); printf("~\n"); // printf("welcome.\n");