IRC channel logs
2025-10-17.log
back to list of logs
<dthompson>it provides an actor model built on top of fibers <dthompson>and the actor model is very much about concurrency and async stuff <mra>dthompson: hm, i definitely need to understand goblins better then! <dthompson>since mailboxes got mentioned: channels are not mailboxes but you can implement a mailbox aka message queue with two channels <mra>dthompson: with the idea being that one fiber sits in the middle, and is responsible for maintaining the buffer, so to speak? <mra>or is it something else <kjartano`>People who have used fibers, how do you synchronise access to standard output? <humm>just found this segfault; I won’t debug this now, but maybe someone knows something <dsmith> GNU Guile 3.0.10.251-549de-dirty <dsmith> 3 (make-non-immediate 0 43) ;; Segmentation fault <dsmith>(that's HEAD from a few days ago) <old>kjartano`: I have a logging module that defered logging and push messages to a fiber <euouae>I'm not sure if I'm going all in on continuations yet but I'm testing the waters <euouae>I never bothered with them in prior apart from a minor scuffle when I was trying to grasp call/cc in scheme <euouae>but seeing as they're an entire compiler techniqnue & used in Guile it's in the way <euouae>Scheme -> Tree-IL makes sense in my head as "desugared Scheme" which isn't too scary, but Tree-IL -> CPS is beyond my understanding <mwette>the disassemble segfault occurs at programs.c:276 w/ code=0 <euouae>ah yeah code is NULL I just checked <euouae>I think the culprit is this /* SCM_SMOBNAME can be 0 if name is missing */ <euouae>no that's the name, nevermind. I'm curious to see what the smob num of proc is, but I have to recompile guile because I guess last time I messed up and I don't have access to cpp macros <euouae>This had nothing to do with (values) as I thought, it's instead about lambdas of no args... <euouae>(lambda () 42) fails too, so I modified the program in the commit message just a bit to make it more obvious <rlb>I don't know programs.c at all, but one thing to check unless you already know could be whether SCM_PROGRAM_CODE can legitimately be 0, or if that might be a sign of a bug elsewhere we need to poke at. <euouae>SCM_PROGRAM_CODE as far as I can tell is the second word of a heap scm <euouae>the first word of that heap scm is scm_tc7_program <euouae>I can't tell you more than that. I don't have 100% confidence in that bug patch, it might be a dumb thing. But the entire test suite passed... <euouae>One thing I can guarantee is that only segfaulting programs are affected by my patch <rlb>Oh first pass I just meant that it could be that it's "better", but still not the root cause. <rlb>But it might also be exactly right, if SCM_PROGRAM_CODE(x) is allowed to return 0,. <rlb>Just didn't know if you already knew that. <rlb>(whether it's allowed or not) <euouae>let me see if elsewhere it's considered <rlb>If it's supposed to be a SCM, then I think dsmith's right, but if it's a "raw" word, then 0 might be legitimate. <euouae>What is the format of a heap scm? <euouae>AFAIK the first word is the tag. What is the format of a program tag? <euouae>Of a heap SCM tagged 'program', I mean <rlb>If you look at bytevectors.h you'll see a case where the words are used as C values, same for strings.c and STRINGBUF_WIDE() etc. where the word is used as a C bitfield. <rlb>but iirc the STRINGBUF_LENGTH() word is a real SCM. <euouae>it's free-form as far as I can tell <euouae>what the format is depends on what the tag is <rlb>See scm.h for many details i.e. "In the beginning..." <euouae>yup but tc1,2,3 are somewhat detailed and tc7 not so much <euouae>it says tc7 is part of the ABI but I doubt it's documented anywhere <euouae>I can tell gsubr.c does not consider the case code == NULL <euouae>it goes directly into code[0] where code is set to SCM_PROGRAM_NAME(...) <rlb>(Also if you haven't already read it "Data Representation" in the info pages is probably worth a look.) <euouae>is that SCM_PROGRAM_CODE reads uninitialized memory <rlb>Right, or someone set it to 0 when that's not allowed, or... <euouae>I know Guile keeps its SCM values 8-byte aligned, but does it zero the between values? <euouae>the SCM tag on the heap takes 4 bytes <rlb>Oh, so from programs.c, ode's not a SCM, i.e. given the uint32_t * coercion. <euouae>yeah I think tc7 stuff can be arbitrary, so the next cells are uint32_t, good point <rlb>and there's no public way in the header to set it, so it might be sufficient to survey programs.c to see what the expectations appear to be. <rlb>(and/or if anything there ever does, or seems like it could set it to 0) <rlb>oh, wait, sorry, it returns a non-const pointer, so we'd need to survey every call to SCM_PROGRAM_CODE() too. <euouae>SCM_PROGRAM_CODE is directly returned by program-code in (system vm program) <rlb>right, just saw that <euouae>It's documented as returning an address. Thus 0 is bad. <rlb>yes, unless 0 means "doesn't have any" <rlb>(which is a common convention, in general) <euouae>since it's 32bit it's not a pointer address <rlb>SCM_PROGRAM_CODE is returning a *pointer*, and uintptr_t isn't 32-bit. <rlb>it's 64-bit on 64-bit architectures, etc. <rlb>oh, nvm was reading the wrong line <rlb>but it does return a uint32_t * <rlb>which is a little wierd <euouae>#define SCM_PROGRAM_CODE(x) ((uint32_t *) SCM_CELL_WORD_1 (x)) <rlb>which program-code turns into a uintptr_t ranged scheme integer <rlb>but still, the fundamental question is whether or not that pointer is allowed to be null <euouae>it's casted as such but it's basically (((SCM *)x) [n]) <rlb>Not sure I follow -- it looks to me like word 0 is being used to store a raw machine pointer to a 32-bit unsigned integer. <rlb>And program-code is returning that pointer as a scheme integer value back to scheme. <rlb>#define SCM_PROGRAM_CODE(x) ((uint32_t *) SCM_CELL_WORD_1 (x)) <euouae>no, it's sizeof(void*), nevermind we've been through that <rlb>no -- see that scm.h section or the info pages, but it's a "word" which these days is going to be 32-bits or 64-bits. <euouae>Okay you're right about everything you're saying <euouae>so the cell 1 pointer is null. On the other hand, I can't force a 0 out of program-code using humm's example <euouae>could it be a bytecode compiler problem? <rlb>Basically I think we have to either reverse engineer whether "code" is ever allowed to be null (via the code, or docs, or git history, or...), or someone has to tell us. <euouae>yeah it's a bad patch... I'll put WIP <rlb>(in order to know what the fix should be) <rlb>Is it bad? I didn't have any real idea yet -- if code's allowed to be 0, then the patch might still be in the running? Would have to learn more about program.c to know what I thought. <euouae>If the patch prevents disassemble-image from segfaulting, you can think of it as a win. But if the patch results in disassemble-image spitting out wrong disassembly, then the problem is elsewhere and it's not fixed <euouae>Because as far as I can tell disassemble-image thinks there's a 0 there because that's what the compiled byte vector told it. <euouae>you'll find 0x45 0x00 in (format #t "~A~%" (compile '(lambda () 42) #:to 'bytecode)). that's the memory I'm reading in `program` under gdb <euouae>e.g. if you do `x/34ub program` in `gdb -ex r --args guile --no-auto-compile bug.scm` <euouae>and compare to the output of (format #t "~A~%" (compile '(lambda () 42) #:to 'bytecode)), it's the same <rlb>...it looks like some of the routines end up using that pointer to grub around in the dwarf/elf data to find the code, and while I'm not sure, some of the related functions look like they might survive a null and just return "nope" (#f), but that still doesn't make me confident either way yet. <rlb>(see for example the uses in debug.scm wrt the addr for find-program-debug-info...) <rlb>(So "still not sure".) <rlb>ACTION heads out for a while <euouae>hm, the bytecode compilation vector gets successfully compiled into a 'value. That makes me think it's probably not an error of compile <mgd>Hello. Does anyone have any guidance on developing with Guile using TDD? I just want to get an idea of what testing frameworks are used, what allows for a quick feedback loop and re-running automatically. All I have used is srfi-64 but I don't have much experience with it <identity>mgd: you can invoke guile on your test suite in ‘compile’ of Emacs or with some shell script that watches *.scm files and runs relevant tests when they change <mgd>I was thinking that. I thought there might be something already created. No problem, more for me to learn <mgd>Can I just ask then, is srfi-64 the preferred option? Or does anyone use something like veritas? <mgd>I don't know if I can share some code then. I wrote some simple code and ran a test using srfi-64. When I compile the file, it rightly fails but the test log that gets created is empty https://paste.debian.net/1401318 <identity>the log file has «Test end: actual-value: "0:0:N" expected-value: "0:0:N:" […]» and stuff. what is your guile version? <mgd>identity how are you running the tests? <mgd>is there a way to print the expected/actual to the console window rather than create a file? <mgd>or a way to run the tests in the repl? <identity>though the error you get is not exactly pretty <mgd>yeah, says for me that the mars-rover module isn't loaded <mgd>Ok, I'll have a look through the guile source code for srif-64 and see if I can figure it out <apteryx>any idea how I can force a thread to appear in guile, for the garbage collector or signals? <apteryx>I'm basically trying to force a Guile multi-thread context and control that unshare returns EINVAL <dsmith>scheme@(guile-user)> (format #t "~s\n" (join-thread (call-with-new-thread (lambda () 3)))) <apteryx>ah, I think I get EPERM because clone would need root privileges <apteryx>not sure why my REPL was seemingly returnig 1 as if everything was fine <apteryx>err, nope, it'sunshare that reeds root, but in a fresh namespace it should be good <mwette>The disassemble bug does not occur if you use (default-optimization-level 0) <mwette>I wonder if the code is optimized to inline and then has no address. <dsmith>mwette, That sounds very plausible <dthompson>unhygienic naming strikes again: nowhere does the definition of 'module-constructor' appear in the guile source. it's a generated name from the 'define-record-type' form in boot-9. makes grep useless. <mra>out of curiosity, does anyone know if it's possible to build guile projects with meson? i'm not sure if it would be necessary to add support for guile upstream, or if it's possible in spite of the lack of explicit guile support <dthompson>does meson need specific support for a language? I've never used it <dthompson>if it's a generic build system I don't see why you couldn't use it <mra>dthompson: it seems to generally require it? i just realised that there's a meson channel on oftc, which would probably be a better place to ask :) <old>mra: there is a guile build system on the way that will be supperior to meson :-) <mra>old: superior to meson is a big promise! <mra>is there anything public about it? does it use ninja as a backend? <old>we are in the process for asking funding to NLnet for making the alpha, beta and initial release of it <mra>old: how do you expect the performance to compare to meson/ninja? one of the reasons that i usually go with them is because of how fast they are <mra>(i use a really terrible old laptop, so these things are unusually relevant to me) <old>mra: I don't know. There is a "Will it scale?" issue for Blue. I want to auto-generate huge projec in C and compare build-systems performance wise <old>I have a plan for performance! <rlb>old: just out of curiosity, assume you're not intending to worry about the current "unusual paths" issue, i.e. you'll do "whatever guile does" on that front? <old>First, we want to support emitting ninja backend if the users wants. Otherwise, just use the scheduler we have in Guile that use fibers <old>you use blue itself to build itself <old>you don't need blue installed <mra>the repo looks like it uses automake? <old>blue is an embeddable build-system, you can copy/paste it in your project and as long you have Guile, you can use it to build your project <old>blue itself use that technique to build itself <dthompson>I'm interested in blue. autotools are terrible but everything else is so much worse. <mra>oh, i'm sorry. completely misread <old>rlb: What dou you mean? I don't understand <mra>dthompson: what's your gripe with meson? i find that it's generally fantastic <old>dthompson: We have plan for goblins also for blue :-) <dthompson>so if blue can retain the good parts of autotools while fixing the completely broken developer experience that would be awesome <old>we might want to have distributed build with blue, like Bazel can do <dthompson>that sounds like something that should be saved for some layer on top <dthompson>but if the extension points are there, cool :) <old>yes. I'm not familiar with goblins enought to see how this could work yet <dthompson>mra: I've never managed a project with meson, I just have experience from packaging software that any build system that isn't autotools based is very annoying to deal with <old>mra: So we aim to be able to generate ninja backend if performance is critical. I also had in mind to generate a pure shell backend so you can compile your project on system where Guile is not present <mra>dthompson: i think that meson is alright? i could be wrong though <old>but to be honest, you can go a long wayyyy with Guile <dthompson>I want a non-autotools build system that has a small dependency graph and supports the usual './configure; make; make install' flow <dthompson>(whether it's 'make' or something else that is *easy* to get onto the build machine) <old>dthompson: that is my entire goal here <old>guile > 3.0.7 is the only dependency <dthompson>most other build systems are too tightly coupled to specific languages or make too many assumptions about the host system <rlb>old: wrt handling paths like (via bash) "touch $'foo\xb5'" -- guile can't if the locale is say utf-8 (now the norm). <old>I've vendor-in fibers in pure Guile for that reason <rlb>But I hope that we'll have an answer for that at some point, and as a workaround (it's not likely common, and not as important for a build system as say a system tool like cp/tar/etc.), you can always set the locale to latin-1. <old>Does Guile interpret paths for things like call-with-input-file ? <rlb>It's all path handling in guile (and envt vars, and...) <old>AFAIK, the kernel just consider paths to be bytevector and that's how Guile should interpret them also <rlb>Guile currently does not. <rlb>And..."it's complicated". <old>I guess yes. There's also the Windows mess to handle <old>And since I don't touch windows machines, well I don't know how to do that basically <rlb>There's a relevant r7rs discussion which has proposed something that might work (noncharacter error handling) -- at some point if that really does seem like what we'd want, I might work on it, but likely only after we decide about utf8. See also (particularly the end) if you're interested: https://codeberg.org/scheme/r7rs/issues/51 <old>rlb: can the problem be entirely avoid if all string literals are in source-file encoded with utf-8? <old>that ought to work for any OS <rlb>It's about the external data -- you cannot even open that file "touched" above. <rlb>if you're in a utf-8 locale in guile right now <rlb>Because you can only use a "string" and it'll get sent to the OS as encoded utf-8 bytes and \xb5 is invalid utf-8. <old>how does other language handle that then? <old>Hmm I see. If I do (scandir "."), I get: foo? <rlb>"it's complicated" (they vary, for example, python had exactly the same mess in earlier versions of 3, but then eventually conceded and implemented "byte smuggling" -- https://peps.python.org/pep-0383/, and rust took a more direct approach, distinguishing String vs OsString, so you can say what you mean iiuc) <rlb>That r7rs discussion is leaning toward something similar to pep-383. <rlb>(and I assume in rust, a tool like cp/tar/rsync would stick to OsString/OsStr) <rlb>(I believe on linux that's "bytes", and might be different on windows/macos) <old>Assume we have an interface in Guile that accepts either string or os-string <old>watherver is the representation of os-string <old>could we use reader-extension to transform literal string to os-string when reading? <old>#os"weird path \xb5" <old>it's kind of a friction for users tho <old>Or maybe the best solution is, don't use weird path in your project ^^ <rlb>There are a lot of considerations -- my impression right now is that given where we are, sticking with "everything's a string" for the first pass is preferable, because if you try to support bytevectors or strings, while that's more efficient for those using bytevectors, it also means a lot more change, and then you have very weak support on the bytevector side. <rlb>i.e. with strings you can easily split/join/etc. all of srfi-13/14, etc. <rlb>Perhaps in an ideal world (with infinite coding/testing resources) you'd have both, so those who want the most efficient interface could just stick to bytevectors, but then you do need roughly two of everything. <rlb>(I was originally leaning toward the latter until I started thinking it through more.) <rlb>And starting with "just fancier strings" also makes guile programs "just work" in most cases, particularly for those who don't (and sensibly don't want to) know about all this. <mra>when writing a user application in guile, the executable is just a guile file beginning with #!/path/to/guile, correct? is there a reason that in the examples that i can find, the --no-auto-compile argument always seems to be passed? <old>mra: the usual pattern is to have a thin wrapper (the script) that is not auto-compiled. That wrapper will call an entrypoint resolved dynamically that is auto-compiled <old>one nice thing of this is the ability to select the implementation. You can have the script that can resolve to a different version of your entrypoint <mra>old: gotcha, that makes sense <mra>i guess this is pretty similar to how python builds executable files