beneroth changed the topic of #picolisp to: PicoLisp language | The scalpel of software development | Channel Log: https://libera.irclog.whitequark.org/picolisp | Check www.picolisp.com for more information
chexum has quit [Remote host closed the connection]
chexum has joined #picolisp
chexum_ has joined #picolisp
chexum has quit [Ping timeout: 268 seconds]
<abu[m]> All those Android restrictions?
<abu[m]> @tankf33der: Does (pwd) work on s390x?
<tankf33der> Works and worked before
<tankf33der> there is test for this
<tankf33der> building new version
<abu[m]> ok, thanks! I'm still on this long error issue
<abu[m]> Let's see if (cos pi) is correct now
<abu[m]> hmm
<abu[m]> I think the test in the tesy suite is not helpful here
<abu[m]> There is *PWD (in '(pwd) (line T))
<abu[m]> So if (pwd) is wrong it goes unnoticed
<abu[m]> Can you try (pwd) in the REPL?
<abu[m]> I want to make sure that string building works, and (pwd) calls 'llvm~mkStr' internally
<tankf33der> : (pwd)
<tankf33der> s390x:~# pil
<tankf33der> : (load "@lib/math.l")
<tankf33der> -> -1000000
<tankf33der> -> "/root"
<tankf33der> -> atan2
<tankf33der> : (cos pi)
<tankf33der> : (in "doesnot" (read))
<tankf33der> !? (in "doesnot" (read))
<tankf33der> s390x:~#
<tankf33der> "doesnot" -- :
<abu[m]> "/root" is too short
<abu[m]> But 'cos' is fine now?
<abu[m]> (The paste is hard to decode ;)
<tankf33der> http://ix.io/480a
<tankf33der> cos is correct now
<abu[m]> Perfect, thanks!
<abu[m]> This was indeed a communicatiion problem between src/lib.c and PilSrc
<abu[m]> A typical endianess-error
<abu[m]> So the question is what is with the error messages?
<tankf33der> what to change to create just U short message?
<abu[m]> An error message?
<tankf33der> yea, to check short message works
<abu[m]> I think they work fine. You tested with "Div/0"
<abu[m]> To test the "Undefined" case, you can change the string in src/main.l
<tankf33der> doing
<abu[m]> line 874
<tankf33der> also i will disable opt
<abu[m]> Good idea!
<abu[m]> And if "U" is displayed, we know it is the length probably
<tankf33der> the same
<tankf33der> i do see U
<abu[m]> Ah, so not the same! "Undefined" was not displayed, right?
<abu[m]> So it is the length
<tankf33der> U was not displayed
<abu[m]> Ah, ok. Good to know.
<tankf33der> disable opt did not helped
<abu[m]> hmm
<abu[m]> But it is not an endianness-issue, right? Cause it works in Solaris?
<tankf33der> yeap
<abu[m]> In Solaris all tests pass now?
rob_w has joined #picolisp
<tankf33der> $ ./pil
<tankf33der> -> "/export/home/mihailp/pil21"
<tankf33der> : (mist)
<tankf33der> : (pwd)
<tankf33der> !? (mist)
<tankf33der> ?
<tankf33der> mist -- Undefined
<tankf33der> $ pil @lib/test.l +
<tankf33der> Bus Error (core dumped)
<tankf33der> $
<tankf33der> another issue here
<tankf33der> maybe coredump on ht, ext modules
<abu[m]> Which machine?
<tankf33der> solaris
<tankf33der> Bus error on fork test
<tankf33der> passed on s390x
<abu[m]> So probably an endianness-issue
<abu[m]> ok
<abu[m]> What is the position in the core dump? 'forkLisp'?
<tankf33der> Type "apropos word" to search for commands related to "word"...
<tankf33der> Reading symbols from bin/picolisp...
<tankf33der> For help, type "help".
<tankf33der> (No debugging symbols found in bin/picolisp)
<tankf33der> [New LWP 1]
tankf33der has quit [Excess Flood]
tankf33der has joined #picolisp
<tankf33der> http://ix.io/480l
<abu[m]> Type "bt" for backtrace
<abu[m]> yes, forkLisp
<abu[m]> I investigate
<tankf33der> http://ix.io/480o
<tankf33der> so one fork works
<abu[m]> I see
<abu[m]> No idea
<abu[m]> I don't know where exactly it crashes. And it must be some global state if it crashes only sometimes
<tankf33der> why sometimes? 100% reproducable.
<abu[m]> Not on s390x, and only second time on Solaris
<abu[m]> As it passes the first time, it must be some global condition
<abu[m]> heap, stack, variables, whatever
<abu[m]> I need the exact position in forkLisp()
<tankf33der> should i enable debug while compile?
<abu[m]> Can you insert (dbg 1 0) (dbg 2 0) ...?
<tankf33der> where?
<abu[m]> In forkLisp
<abu[m]> Several places
<abu[m]> Then we know from the number in the second arg where it is
<abu[m]> I always do a binary search
<abu[m]> Insert three dbg calls
<abu[m]> Then divide down the position
<abu[m]> (if it is reproducible)
<tankf33der> forkLisp is huge
<abu[m]> yeah
<tankf33der> i do understand where to insert lines
<tankf33der> i do not understand where to insert lines
<abu[m]> good
<tankf33der> *not*
<abu[m]> ah
<abu[m]> Any place
<abu[m]> At least at the beginning and end of parent and child part
<abu[m]> forkLisp() has no 'ret', so it goes through from beginning to end
<abu[m]> I would put one at the very start
<abu[m]> Then two in the child part and two in the parent part, always at beginning and end
<tankf33der> i will not waste time for this
<tankf33der> i do not understand where insert
<tankf33der> i waiting for patch or ignore
<abu[m]> There will be no patch if we don't find the error
<tankf33der> patch for insert
<abu[m]> Pil21 will never run on big-endian machines
<abu[m]> Where is the problem? Put (dbg
<abu[m]> Put (dbg 1 0) at the beginning
<abu[m]> Then look at the 'cond'
<abu[m]> There is a child part and a parent part
<abu[m]> ((=0 @) # In child
<abu[m]> next line (dbg 2 0)
<abu[m]> Child part ends with "0 )", i.e. it returns zero. So before that line (dbg 3 0).
<abu[m]> Same in parent part
<abu[m]> Then you know if it crashes in parent or in child, and divide that part down
<abu[m]> I parent I would put after "(let Pid @" and before "Pid ) ) ) ) ) )"
<tankf33der> http://ix.io/480s
<abu[m]> Yes, but not at the end of child code?
<abu[m]> Is it still reproducible?
<tankf33der> add (dbg 22 0)
<tankf33der> why you ask about reproducable/
<tankf33der> why you ask about reproducable?
<tankf33der> this is paste link
<abu[m]> It could be a heisenbug
<tankf33der> http://ix.io/480t
<tankf33der> link shows it reproducable
<abu[m]> T
<tankf33der> http://ix.io/480u
<abu[m]> 1, 2 and 3 are there. We don't know if child code passed, as there is no dbg
<abu[m]> ok, 22
<abu[m]> So it is in parent?
<tankf33der> dont ask
<abu[m]> I then always remove unnecessary dbg`s
<abu[m]> Only three are needed
<abu[m]> or two
<abu[m]> I move them when the area of crash is known
<abu[m]> binary search
<abu[m]> You can extremely quicky search even large code pieces
<abu[m]> (dbg 1 0), (dbg 2 0) and (dbg 3 0)
<abu[m]> One term with editor, one for build and test
<abu[m]> Cycle time of seconds
<tankf33der> last digit is 22
<tankf33der> so it pass child code
<tankf33der> so it passed child code
<abu[m]> If it crashes between 2 and 3, I mover 1 to the place of 2, and two in the middle towards 3
<abu[m]> yes, child seems good
<abu[m]> then 1, 2 and 3 in parent part
<abu[m]> just a few lines ;)
<tankf33der> : (unless (fork) (wait 60000) (bye))
<tankf33der> 3
<tankf33der> 2
<tankf33der> 4
<tankf33der> 1
<tankf33der> 22
<tankf33der> Bus Error (core dumped)
<abu[m]> You quickly get the exact line
<abu[m]> Too much!
<abu[m]> 1 2 and 3
<abu[m]> and you don't need to post all here, just the bad line
<tankf33der> 3 in the parent
<abu[m]> yes
<abu[m]> beginning, middle and end
<abu[m]> then move the lines
<tankf33der> so i search in parent?
<abu[m]> yes, must be parent
<tankf33der> but why last is 22 ?
<abu[m]> You see immediately if 1 is printed but not 3
<abu[m]> 22 was in child?
<abu[m]> remove it
<abu[m]> Don't put too many, it just confuses
<tankf33der> you do not follow my links i posted and write nonsense
<tankf33der> again and again
<abu[m]> yes, it just confuses
<abu[m]> It is very easy! Just put two dbg's and search interactively!
<abu[m]> Fast edit/compile/test cycle
<abu[m]> Five seconds per cycle
<abu[m]> And you know the exact place
<abu[m]> (if it is indeed no heisenbug)
<abu[m]> No need to past all the links here, they must change anyway at each step
<abu[m]> I can't help from here, it is interaction on your machine
<tankf33der> http://ix.io/480x
<tankf33der> open this link and tell me order is different?
<tankf33der> open this link and tell me WHY order is different?
<abu[m]> Parent and child run in parallel. Order is not predictable
<abu[m]> Just put 2 dbg's!
<abu[m]> In parent
<abu[m]> 1 and 2
<tankf33der> i did not get 6
<tankf33der> on second run
<abu[m]> If 2 is reached, you move it further
<abu[m]> Remove 6!!!
<abu[m]> Please!!! Jusy two links
<abu[m]> I can't help, and can't follow all your links
<tankf33der> this is the problem
<tankf33der> you cant sync with my machine on my side
<tankf33der> but i sync with you
<abu[m]> I don't want to sync
<abu[m]> Why can't you just put two dbg's?
<abu[m]> And then know if it crashes between
<abu[m]> If it crashes, move the links accordingly
<tankf33der> http://ix.io/480y
<abu[m]> I'm repeating myself
<tankf33der> it crashes here
<tankf33der> i did not see 6 on second run
<abu[m]> between 5 and 6?
<abu[m]> good!
<tankf33der> yes
<abu[m]> So move 6 a few lines up
<abu[m]> into the middle
<abu[m]> then perhaps 5 down etc
<tankf33der> now will find exact line
<abu[m]> Seems that either the Cld: pointer is bad, or nonBlocking
<abu[m]> Put one before and one after nonBlocking
<abu[m]> then you see
<tankf33der> (Cld: buf null) # No buffer yet
<tankf33der> here crashing
<abu[m]> Cool!
<abu[m]> So it is Cld:
<abu[m]> It is a pointer to a structure
<abu[m]> tough
<abu[m]> These structures are allocated globally
<abu[m]> explains why it crashes the second time, as the first one was allocated before
<abu[m]> We are getting closer! Let me think.
<abu[m]> Must dig into it, forgot the details :e
<abu[m]> s/e/)/
<abu[m]> No idea
<abu[m]> I see no dependency on endianness
<tankf33der> And it works on s390x
<abu[m]> yeah
<tankf33der> better concenrate on linuxes for both endianesses
<abu[m]> Is there a Linux where you can change endianness?
<tankf33der> yeap
<tankf33der> i run alpine linux on qemu for s390x
<abu[m]> cool
<abu[m]> Is it difficult to set up Solaris? In qemu?
<tankf33der> Imposible
<tankf33der> i havr real hardware
<abu[m]> ok
<abu[m]> How does it come that you have so many kinds of hardware? Are you working in a computer museum? ;)
<tankf33der> No :)
<abu[m]> Are you collecting hardware? Or is it business?
<tankf33der> Company have a huge number of systems, legacy and modern
<tankf33der> i am sysadmin and have access
<abu[m]> Very cool!
<abu[m]> I forgot: How was the state on s390x? Did all tests pass now?
<abu[m]> hmm, no, the errors
<tankf33der> All my tests passed
<tankf33der> the only issue is Undefined strings
<abu[m]> yeah
<abu[m]> error messages
<abu[m]> strange
<tankf33der> Some of them
<tankf33der> div/0 and undefined is the same in the root, right?
<abu[m]> yes, some, and it is not the length
<abu[m]> Same error handling, but the situation that caused the error is different
<tankf33der> btw, ext and ht works now on s390x
<abu[m]> But we did not change anything?
<tankf33der> tonight changes helped
<abu[m]> yes, could be
<tankf33der> : (proc 'pil)
<tankf33der> proc -- :
<tankf33der> !? (proc 'pil)
<tankf33der> proc is broken too
<tankf33der> i am expecting some output
<abu[m]> yes, there is an error before output
<abu[m]> invisible error again
<tankf33der> (call 'ps) works
<abu[m]> What if you genenrate errors directly?
<abu[m]> (quit "Foo" 7)
<abu[m]> With various arguments? Perhaps this shows a pattern.
<tankf33der> the same output with x64
razzy has joined #picolisp
<razzy> hello, everything smooth?
<abu[m]> Hi @razzy, nice to see you! โ˜บ/
<tankf33der> http://ix.io/480X
<razzy> abu[m]: you too :]
<tankf33der> found some error messages does not print
<tankf33der> (quit "34093434834034930483403434340893408934034893408934" 12343434343434343434)
<tankf33der> this line is not working
<tankf33der> always
<razzy> anyone tried put pil21 into firejail sandbox? i have errors
<tankf33der> (quit "m" 1234567890) is not working
<tankf33der> so problem in the second arg
<tankf33der> (quit "m" 123456789) is last digit when working
<abu[m]> indeed
<tankf33der> on x64 works on any length
<abu[m]> I see, not the string but the Lisp item
<abu[m]> And then the Lisp term is printed but not the message
<razzy> why i can read user input with (line) from REPL but not when execute from ./pil script?
<abu[m]> You can
<tankf33der> s390x:~/pil21# pil
<tankf33der> ddddd
<tankf33der> :
<tankf33der> : (line)
<tankf33der> -> ("d" "d" "d" "d" "d")
<tankf33der> works here
<abu[m]> @razzy has the old misunderstanding
<razzy> tankf33der: works from repl with me too. but when i run script it ommits
<abu[m]> The current input channel is the script of course
<razzy> abu[m]: I have lots of old misunderstandings
<abu[m]> We had this question here many times
<abu[m]> โ˜บ
<razzy> i will look in history next time.
<abu[m]> Anyway, reading is always from the "current input channel"
<abu[m]> @tankf33der, I have an idea!!!
<tankf33der> i must run
<tankf33der> afk
<abu[m]> gPrintf()
<abu[m]> ok
<abu[m]> I was wrong anyway. Not gPrintf()
<abu[m]> When @tankf33der is back: Stupid question perhaps, but is the stack growing downwards?
<tankf33der> How to find out?
<abu[m]> hmm
<abu[m]> (buf A 10 (msg A) (buf B 10 (msg B)))
<abu[m]> If the second number is smaller than the first, the stack grows downwards
beneroth_ has joined #picolisp
beneroth has quit [Ping timeout: 268 seconds]
<tankf33der> I found in google stack grows down
<tankf33der> hppa is up
<tankf33der> i will test asap.
<abu[m]> ok
razzy has quit [Ping timeout: 248 seconds]
<abu[m]> I added a size check to gPrintf()
<abu[m]> used in error message
rob_w has quit [Remote host closed the connection]
<tankf33der> back
<tankf33der> : (buf A 10 (msg A) (buf B 10 (msg B)))
<tankf33der> 4397492333488
<tankf33der> 4397492333856
<tankf33der> -> 4397492333488
<tankf33der> :
<abu[m]> ๐Ÿ‘downwards
<tankf33der> testing latest patch
<abu[m]> I try to find a way to get more info in the error messages
<tankf33der> the same behaviour
<abu[m]> ok
<tankf33der> why works on shorter second argument?!
<tankf33der> : (quit "1234" 1234)
<tankf33der> 1234 -- 1234
<tankf33der> s390x:~/pil21/src# pil
<tankf33der> ?
<abu[m]> yes, this is the interesting point
<abu[m]> The arg destroys the buffer somehow
<abu[m]> Let's experiment with this: (stderrMsg ($ "|%s|\n") Msg)
<abu[m]> Can you insert it after (gPrintf Msg 240 Fmt Arg) in src/main.l?
<abu[m]> Then we see if the message arrived here
<abu[m]> If not, it must have been damaged before, and we move that line
<tankf33der> doing
<tankf33der> how i should call quit ?
<tankf33der> with longer argument, right?
<abu[m]> Yes, the one which disappeared for certain second args
<abu[m]> long second arg, right?
<tankf33der> ok
<tankf33der> http://ix.io/481O
<abu[m]> Cool, it is empty "||"
<abu[m]> So now take this line out, and put it after
<abu[m]> Msg (bufString Nm ...
<abu[m]> in _quit in main.l
<abu[m]> before (err 0
<tankf33der> doing
<tankf33der> http://ix.io/481P
<abu[m]> ok, twice, so you did not remove the first one
<tankf33der> yeap
<tankf33der> should i?
<abu[m]> Interesting, the second place now has the value too, right?
<abu[m]> Before it was empty
<tankf33der> yeap
<tankf33der> let me remove first
<abu[m]> good, but not a problem
<abu[m]> just to be sure which is which
<abu[m]> You can also add other info e.g. before the first "|"
<abu[m]> ($ "1 |%s ...
<abu[m]> I would propose as next step:
<abu[m]> (stderrMsg ($ "|%s|\n") Arg)
<abu[m]> Into the first line of 'err'
<abu[m]> So far we know before err Msg is good
<abu[m]> It should directly go into 'Arg' in 'err'
<tankf33der> http://ix.io/481X
<tankf33der> now do Arg variation
<abu[m]> good
<abu[m]> We are close to find the bad spot
<tankf33der> http://ix.io/481Y
<tankf33der> now broken for both calls
<abu[m]> yes, but we still reproduce the error
<abu[m]> Now let's break it down: http://ix.io/4820
<abu[m]> Must go wrong somewhere here
<tankf33der> http://ix.io/4827
<abu[m]> Wow, it must be (b8 240)
<abu[m]> To be sure: http://ix.io/4828
<tankf33der> (stderrMsg ($ "2 |%s|\n") Arg)
<tankf33der> is this correct ?
<tankf33der> should be Msg
<tankf33der> no?
<abu[m]> hmm, could be both
<abu[m]> Arg is correct
<abu[m]> Msg buffer is just allocated, not initialized yet
<abu[m]> It is initialized by (gPrintf ..)
<tankf33der> doing
<tankf33der> http://ix.io/482b
<abu[m]> Oh, not (b8 ..)
<abu[m]> It is (gPrintf ...) right?
<tankf33der> http://ix.io/482c
<tankf33der> this patch
<tankf33der> i am synced with you
<abu[m]> yeah
<abu[m]> What is wrong with gPrintf? I study it.
<abu[m]> oh! Could it be the 240?
<abu[m]> I expect LLVM to cast it to int32_t
<abu[m]> Because it is declared in @src/dec.l as: (de T i32 gPrintf (i8* i32 i8* i8*))
<abu[m]> Can you change the call to (gPrintf Msg (i32 240) Fmt Arg)
<abu[m]> I think this should not be necessary, but perhaps they have an LLVM bug?
<tankf33der> http://ix.io/482e
<abu[m]> But if 240 is passed as 64 bits, an gPrintf expects 32 bits, it gets zero on big endian
<abu[m]> ok :) This was not the reason
<abu[m]> I found a minor glitch in @src/dec.l
<abu[m]> line 192
<abu[m]> The return value should be "void"
<abu[m]> (de T void gPrintf (i8* i32 i8* i8*))
<abu[m]> Can you try this? In my understanding it should not matter, as no return value is used
<tankf33der> doing
<tankf33der> http://ix.io/482h
<tankf33der> FIXED
<abu[m]> Wow!!!
<abu[m]> So the (ignored) return value did matter!!
<abu[m]> Perhaps it has to do with register allocation on that ancient architecture
<abu[m]> Strange!
<abu[m]> Buit anyway, very good โ˜บ
<abu[m]> I released the change.
<abu[m]> So s390x now completely passes all tests??
<tankf33der> yeap
<tankf33der> running again
<abu[m]> I hope there are not more errors of that kind
<tankf33der> tests will run more than 20mins
<abu[m]> good
<abu[m]> I check @src/dec.l meanwhile
<tankf33der> qemu is slow
<tankf33der> qemu is slow in emulation mode
<abu[m]> I believe so
<tankf33der> x64 is ok
<abu[m]> ๐Ÿ‘
<tankf33der> http://ix.io/482n
<tankf33der> ext:Snx
<abu[m]> Loading shared object files seems to fail
<abu[m]> So this is a new problem
<abu[m]> s390x ?
<abu[m]> ok, yes, the prompt says it ;)
<abu[m]> 'native' also opens shared libs
<abu[m]> Does native work?
<abu[m]> (%@ "getenv" 'S "TERM")
<tankf33der> s390x:~# pil +
<tankf33der> : (%@ "getenv" 'S "TERM")
<tankf33der> -> "xterm-256color"
<tankf33der> :
<tankf33der> it worked and not time to time
<tankf33der> it worked today, iirc
<abu[m]> Depending on the library?
<abu[m]> "@" is the binary itself, so it is always found
<abu[m]> Perhaps you can see something if you 'strace' the 'ext:Snx' call
<abu[m]> The library path it tries to open
<tankf33der> s390x:~# pil
<tankf33der> -> "S"
<tankf33der> : (ext:Snx "sss")
<tankf33der> :
<tankf33der> it works now
<tankf33der> i removed opt from Makefile
<abu[m]> Good idea! So not our fault it seems ๐Ÿ˜‡
<tankf33der> s390x:~# pil @lib/test.l +
<tankf33der> OK
<tankf33der> :
<tankf33der> enough.
<abu[m]> ๐Ÿ‘
<abu[m]> This means s390x passed all tests?
<abu[m]> No more omitted, but opt swiched off
<tankf33der> issue closed.
<abu[m]> good
<abu[m]> But Solaris fork problems remain
<tankf33der> solaris is dead.
<abu[m]> true
<tankf33der> linux and x64 won.
<abu[m]> Let's ignore it?
<tankf33der> sure
<tankf33der> who cares.
<abu[m]> All right
<tankf33der> s390x failed on my tests now
<tankf33der> even with disabled opt
<tankf33der> s390x:~/pil21-tests# pil math.l
<tankf33der> [math.l:77] Stack overflow
<tankf33der> s390x:~/pil21-tests#
<tankf33der> Segmentation fault
<tankf33der> stack enough as always before
<tankf33der> this is something new
<tankf33der> because it was ok yesterday.
<abu[m]> Native floating point calls
<tankf33der> this is (fibo 10000)
<tankf33der> damn
<tankf33der> fibo function with memoization
<abu[m]> math.l:77 is which math.l?
<abu[m]> @test/lib/math.l has only 41 lines
<abu[m]> So it is your test file?
<tankf33der> http://ix.io/482u
<tankf33der> crash this code
<tankf33der> (fibo 1000) is ok
<tankf33der> i will enable opt and will pass
<abu[m]> tough
<tankf33der> (gc 32) did not helped
<abu[m]> If it works with opt, then perhaps too much stack is used without opt?
<abu[m]> (fibo 1000) works?
<tankf33der> i wrote it several lines above
<tankf33der> recompiling with opt
<abu[m]> What do you mean you wrote above?
<abu[m]> ah, sorry
<abu[m]> 1000 is ok
<abu[m]> So I think it is really a stack overflow
<abu[m]> Without opt it uses lots of stack perhaps
<tankf33der> testing
<tankf33der> passed with opt
<abu[m]> as expected
<tankf33der> recompiling without opt and setuping more stack
<abu[m]> ok
<tankf33der> passed with double up stack
<tankf33der> issue closed.
<tankf33der> afk.
<abu[m]> You could measure the stack usage with and without opt easily
<abu[m]> (cons (buf B 1 B) (let N 7 (recur (N) (if (=0 N) (buf B 1 B) (recurse (dec N))))))
<abu[m]> This gives a range
<abu[m]> The stack used by 7 recursions
<abu[m]> Or, even better, return the difference:
<abu[m]> (- (buf B 1 B) (let N 7 (recur (N) (if (=0 N) (buf B 1 B) (recurse (dec N))))))
<abu[m]> Gives 1408 bytes here on Android
<abu[m]> I will post this in @PicoLispREPL
<tankf33der> I remember rosettacode task about this
<abu[m]> Yes, I think it did not measure the size but counted the recursions until it crashed
clacke has joined #picolisp
aw- has quit [Quit: Leaving.]
aw- has joined #picolisp
alexshendi has joined #picolisp
chexum_ is now known as chexum
alexshendi has quit [Read error: Connection reset by peer]
alexshendi has joined #picolisp
alexshe59 has joined #picolisp
alexshendi has quit [Ping timeout: 255 seconds]
alexshe59 has quit [Ping timeout: 248 seconds]