 All right, so let's go through some examples and this will be a bit of a scuffed class because I guess their wireless went down Yikes, well your wireless I guess works, but mine doesn't so It's back up Mine is still dead Yep, mine's still dead. So it's recording. So I'll just upload it to YouTube later. So well, I guess we'll have to struggle through it and Do what we can do out of this So let's look at some examples. So here is the simplest program. We're going to have so remember There's a standard file descriptors zero one and two. So what we're going to do is we're going to declare a buffer. That's a size of 4096 which is a size that the kernel really really likes that we'll see why that is later and Then all it does is in this while loop So this while loop just calls read over and over again and that read system call will return how many bytes are actually filled in that buffer and when there's Yeah, and just while we're reading some bytes. So while we're reading more than zero bytes All that's going to do is write to file descriptor one That buffer and how many bytes it read from that buffer? So every read system call it fills up a buffer and then we write that back out to file descriptor one So here we do some light error checking. We see if Write returns an error. So it's like a standard C wrapper function. So if it returns native one There's some type of error and then we go ahead. We'll print out that error will kill this process and Don't let go on then here We'll just make sure that we write out the same number of bytes We read in so everything lines up and we don't have any weird partial writes or anything like that and then We hit the bottom of the while loop. So we just go over and over again So we keep on reading over and over again, and then the only time will break out of this while loop is when read return something that is zero or less. So if it's negative one that means it's an error and we'll print out that error number and Otherwise we'll assume that the bytes read should be zero which indicates. Hey, you're done. That's it That's all you can read and then we would just go ahead and exit so if we go ahead and Run this program So it doesn't do anything. So it just sits there. It's not finished yet because it's waiting for us to type something So if I type hello It throws it back out at me, which is cool every time I press enter it Works like that. So hi press enter spits it back out. So does this look like any program you've ever used before? Who can hazard a guess what this program actually is? Yeah Echo Is it echo echoes fair? No, it is not echo because if I type echo it just yeah throws it back out at me Any other guesses? So what about cat? So if I do cat well, it kind of looks the same already and if I do hello hit enter says hello back Huh weird and if I say hi and press enter it throws hi back So spoiler alert that cat program. We actually just wrote cat that is cat whatever we just wrote reading from zero and writing to one is Exactly what cat does cat is a little more complicated than that but not really because Everyone okay show of hands if people have used cat like Have people use cat like that before yeah, so everyone's use cat like that So if I use cat like that, what do I get I get the contents of that file spit back out at me Okay, well if I want something like that I'm without rewriting our core logic of a read write thing that just reads everything from zero and writes everything to one well What I can do which is why? Which is why I recommended in lab one that you should use oh god That you should use the open system call because it's a bit closer to what we actually want So without rewriting anything. I'll Without rewriting the core loop. I'm going to add another argument So it will take up to two arguments and say hey if I have a second argument So the first arg is going to be the program name by convention And then I'll say hey if there's two arguments. I'll take the second one as a file name So if I get a file name, I'll close file descriptor zero so I can close whatever I've opened I'll just say hey, I'm not going to use it. I'm not going to use that as standard input Whatever you gave me I'll close it and then I will open the first argument as a read only file So I'll just use it as a file and as part of open you get a file descriptor and the rules of Linux and Most other ux's are it will use the lowest file descriptor whenever it creates a new one for you So this file is going to be represented by file descriptor zero So it's just going to spit out file descriptor zero back out me and now instead of being Whatever it was before file descriptor zero is now a file So if I do that, I'll check for errors and then otherwise My program is exactly the same as before So if I go ahead and do that well, then my build open example I can go ahead and Do what I would do for cat where I want to see the contents of the file and I get the contents of the file Because all it does is it doesn't care. It just reads from file descriptor zero file descriptor zero could represent Whatever and that's kind of the nice thing about you nix's you don't have to rewrite your program You can write like very simple things that don't really do that much that are actually fairly powerful So any questions about that? Yep so the Read and write system calls all they want is a file descriptor and you don't know what that actually represents And it's just by convention whenever you start a program zero is standard in and that should be something I should be able to read from and then One is standard out, which is something I should be able to write to it's just by convention And you have no idea whatever they represent So I didn't express it. I just read from file descriptor zero and By default if you launch like an application on your terminal Whatever you type will go your shell will make everything go to file descriptor zero for you So that's the nice thing. You don't have to write any like keyboard handling code. You just get bytes Yeah So here if I tried to read file descriptor one So if I try to read file descriptor one Usually if you do that that's really bad because file descriptor one supposed to be something you actually only read from And it's like undefined if you can write to it or you're supposed to only Write to file descriptor one not read from it, but if I go ahead and do this I assume it's going to work So let's go ahead. Oops So it still works, which is kind of weird. I see your face So it's kind of weird, but remember last class when we actually saw In our shell and whatever application gets launched there what the file descriptors actually are so file descriptor 012 by default represent like the pseudo terminal thing and file descriptor 0 1 and 2 all point to the exact same thing. So in this case They all point to the exact same thing. So in this case It doesn't matter which one we use because they're all the same But if I like gave a file to that instead some really weird things would happen because we can change what file descriptor zero is So you shouldn't do that, but in this case it works Let me undo the So the convention is you should only read from file descriptor zero and if you do do that Like sometimes it might work, but other times it might fail really really bad and you'll have to kind of figure it and you'll see All right, any other questions? Okay, so here I'll go back and show you a few fun things first. Oh, right and also Some of you may have thought there's like an end of file or something weird With that like a special end of file character when you're finished with a file But that's not the case. So how you signify end of file is if I Type this and you know type cat and I'm here. I Want to close this eventually and like end the process? So the only way to actually end the process cleanly is how would most of you end the process? Yeah All right, so anyone else use anything other than control C Do you know what control C does? What was control C do? Okay, so some people just like panic control C. We're all good. So yeah, I can control C I see some weird stuff there, which we'll explain today that like 130. It's kind of weird and It gives some type of error which indicates something bad happened Well, if you actually want to like this to exit cleanly what you should actually hit here is control D I hit control D to stop So what control D will do is actually say hey, I'm done I'm done giving information to this program. So I will just close it and It will signal to that process that hey You can't read any more information and that read system call looking at the code We can kind of deduct what it did since it exited nicely. Oh, please close so to get break out of the loop it would have Read back something that is zero or less and it didn't get a negative one And we have an assert there that bytes read is zero before we exit. So The only way when we press control D It just makes read return zero bytes and that indicates you're done with the input So there's no special end-of-file character. There's nothing like that The only way you know you're not getting any input anymore is if read return zero That's it. Yep So the question is what is it reading when I'm not typing anything? So like I type something and now it's just sitting here waiting for me So what read will do is read is kind of like that wait system call that will block until something happens So in this case read is going to block. I've read all the input That's there already. So it's just going to sit there and block that process until it gets some more input. Yep Control C is not copy on Linux's Yeah On Windows. Yeah, that's the default thing It might work on the Windows terminal. Oh, no, I haven't really used the Windows terminal Doesn't power show it copies. Okay. Oh, no, it does whatever will we'll figure it out Okay, but it won't quite do that because it's Windows. So we'll figure out what it actually does so go back So, yeah, so Control D is when you want to stop something and say hey I won't give you any more input and that's the end of file. There's no special end of file character That was all alive every anyone's ever told you that at least on Linux. That's not a thing Because that wouldn't make sense. So remember like that read interface is really really generic It just gives you some bytes and if there was a special end of file character Well, it would have to be a value of something and then whatever that value was Well, you couldn't use it to actually as information because it would represent end of file Which is something which would restrict you which is something you don't don't want so end of file means Read return zero So again, here's read if you want to look at there's a man page so you always need to check for errors again same thing zero negative one means there's an error and it'll set that global variable called error now and then write same things that returns the number of bytes written and you can't really assume it's always successful most of the time it will be and Again, you need to save error know like I'm doing because another function might set it because if it's doing print F Or something like that. Well, that will call write and might itself have an error of some variety So There's also another part of it. So it's like who's giving me bytes that I'm reading So we know there's another process that Was writing bytes to whatever file descriptor zero was that I'm reading from so there's another process that wrote bytes And I read them and then whatever bytes I wrote out something else must have read them because I actually saw what was typed So even without that you get some communication Essentially for free that you don't have to set up and to this point. You probably didn't even realize what was going on It just kind of worked So here's that thing to illustrate that the standard file descriptors are quite powerful So remember what I did I just opened I closed file descriptor zero and I opened the file And it was filed descriptor zero and then without changing my program It just did cat things and it could dump the output of my file So what I could actually do instead is Do some little shell tricks I'll show you so instead of running that open example and then giving the file name Well, there's some standard stuff you can do with like a Linux shell that plays with the file descriptors for you So instead of doing you know open example with that open example file And then getting the arguments and opening the file and doing all that well the shell actually has some nice stuff for you So if you type something like that that arrow It basically tells you hey that file I want to be the Standard in file descriptor and the shell will go ahead and open that file for you and replace it with file descriptor zero So I didn't actually have to write that open system call or do anything so to illustrate that Let me go back And I'll show you that so With my example that didn't even have a read system call. It was just read write example Well, I could use that arrow that says Basically, I'll give you a file on the right and replace that with standard in so if I do that What was it called? I get the output of that file directly and I never even had to write an open call at all I just kind of let my shell do it for me and you can write programs like this I can use files that don't even have an open call in them whatsoever if you know how to use the shell So that's pretty cool And then other things you can do so Some other things you can do is this Line character. It's actually called a pipe. So you can actually redirect across multiple processes So I could cut you know cut that file name Which is going to output All of the contents of this file to the standard out to its standard out And then what this character does is essentially connect the two processes together So it will essentially make Anything this writes to standard out This process will read As standard in so anything it writes the other one will read and that's how you connect things together So if we do something like that, let's go back So if I can't say read write example, I can use that pipe character And then use my read write example program and I'll get the same contents of the file, but now you know This program would have opened that file And wrote it to standard out And then in this process because of this character connecting them together Whatever it read from standard out or standard in it wrote the other Or it read information from the other processes standard out and then We know what this does it just spits everything it read Back out to standard out and we actually see the contents, but it's kind of a kind of a roundabout way So any questions about that one, which is kind of weird. Yeah So the question is is it okay to think of standard in standard out as files? Generally you want to just think them Think of them as just something to read bytes from and write bytes to We'll see all different things that they could actually be So files is one we already kind of know and now we kind of know This character kind of connects them together. So I wouldn't quite say there were files for this There's like some magical thing that glues them together So and we'll kind of figure out what that is later Any other questions so spoiler alert because of that like Read bytes write bytes being super generic while Your web browser whenever it wants to communicate with stuff essentially uses read and write because that's the only option And now that represents a network connection instead of a file or instead of whatever magical thing this is. Yeah So every process is independent of each other So I only change the file descriptor force specific process, which doesn't change anything else So Kind of what we've already been learning about everything being independent So something forked at some point, but after that all the processes are completely independent So they don't really monkey with each other Yep Yeah, so both of these programs So this will be a process and this will be a process And they'll be running at the exact same time And then just communicating through that those file descriptors But there'll be two processes that exist at the exact same time Yep Okay, so we want to figure out what in the heck control c does So, yeah, I've preempted this so you can also use control c to stop, but we don't exactly know what it does and why So what control c does is it basically interrupts your program So we've seen interrupts before in kind of other courses. So this is a interrupt for normal programs So you can actually send them and that's what you do when you hit control c so a interrupt is In this context, they just call them signals, but they're basically just interrupts for processes And there are different reasons for interrupting your processes and they're just given a number So a kernel will interrupt your program with some number that indicates some interrupt And it tells you, you know, based off that number, you're supposed to deduce what actually the reason for it is So if you press control c that will send an interrupt to that process Which is called sig init. So all of them will be called sig something And sig init is supposed to represent an interrupt from a keyboard. That means hey, I Interrupted you the user interrupted you so you should probably do something so What the default handler will do is well, I didn't write anything that has to do with signals in my program I just wrote a main and some reads and writes and that was it So the kernel and or c will have some default handlers for you like interrupt handlers I you're hopefully kind of used to And by the the default handler for sig init or any of them is just to exit that process straight away and set an exit with an exit status of 128 plus whatever that signal number was So if we go back to this Whatever we did build Although I just didn't know Whenever I did this and I hit control c Again this number here is the exit status of the process if it's not zero So it exited with 130 So we can you know do some simple math to figure out what signal number that is so 130 minus 128 is two So our process got sent signal two and then just exited Hmm weird So you can actually set your own signal handlers with this system called called sig action and it Is just a hopefully you've written interrupt handlers before maybe but it's just a function That doesn't return a value and takes an in argument Which is the signal number and then you're free to do with it Whatever you want on linux x86 or linux arm whatever these are the standard numbers So two is sig init, which is interrupt from keyboard Nine is sig kill, which sounds slightly violent, which is terminate immediately then sig 11 is Something you've all probably got before so that is Seg Sig seg v which is a seg fault. That's where the name comes from. That's when you have screwed up malloc Which probably everyone has done and then there is 15 which is sig term which is like terminate but terminate nicely and we'll see what the difference between those are So A signal how that works whenever it gets sent to your process your process essentially stops executing whatever it was executing and that And will jump immediately to that single handler and run until it's completed And then if it returns it starts it continues wherever it left off so If you want to like are you correct us? It's kind of like those two processes running at the same time. You don't know what order they're going to come in And for signals you have no idea when a signal is going to come in So you have no choice if you register a signal handler It's just going to run whenever a single handler comes in if it's a bad time. Well, that's too bad for you So this is an example of concurrency switching executions like that, which we'll see more in depth later in the course But basically it just switches your execution So let's go ahead and show signal example and press control c so In signal example, what do I have? So in signal example Just checks to see if it has arguments. Otherwise, it's going to be exactly that Open example, so that open read and write. So I'm just adding signals to that program we had initially So first it will go ahead Open the file as file descriptor zero if there's you know, if we give it an argument Otherwise it will register two signals So it will register sig init, which is whatever gets sent when we hit control c And then register sig term, which is the nice way of shutting down So let's go up. So register signal It's kind of a bunch of boilerplate code that you don't really need to be terribly concerned about But basically you just set a bunch of things all the defaults are probably fine The only thing you actually is important to give it is Which function to run when a signal comes in? So here I basically tell it For these signals, I want this handle signal function to run whenever a signal comes in And then this sig action registers them with the kernel So whenever someone types control c or whatever, then this handle signal function is going to run So let's see what that looks like and here's my handle signal function So all it does is say screw you I don't care and it tells you about it So let's go ahead and run that So here's the same program like it was like my cat, so I'm typing I'm typing now before this lecture you would have just typed control c to get out of it Now if I hit control c Oh something weird It says ignoring signal two, which is what I thought but I thought it would just kind of ignore me and continue on Bygone error from read So that's interesting So by programming somewhat defensively we know that hey system calls can fail Just because a signal comes in so It Failed and got an error that said interrupted system call Please retry So we didn't handle that so we can go ahead and handle that since that's something that we know now that can happen So to handle that In my loop here, I can check. Hey does read return an error If read returns an error, I'll check error no and this is the error no that represents Hey a Your system call got interrupted. So if my system call gets interrupted I go. Oh, yeah, sure Don't worry about it continue and just read again because I know that actually wasn't an error I just got interrupted. So I'll just restart and try again And then otherwise it was really an error. So I'll just break out of the loop So now with our new and improved one that will restart system calls I can go ahead. I run this it looks the same as before Hello, and then if I hit control c now This says screw you And I I can't type anything it's still work and it still works But I type control c again It says screw you So you can actually do this if you want like if your friend hasn't taken this course yet And you want to give them a program just do this where it ignores everything that happens to them And they probably won't ever figure out how to actually get rid of it So That's something you can do So let's figure out how to actually get rid of it So if we want to actually get rid of it, well The nice way of doing it is to send a signal. So signals are there's that nice signal. That's like hey terminate please so You would think to send signals to a process it would be like a system call like Send signal or something like that some nice name that makes sense The system call to send signals to a process is called kill Why it's called kill. I have no idea but Kill all that is is to send a signal to a process. So if I want to kill what's running So right now This is the thing that's running. So I'll get its process ID So the kill command will basically just do the system call for you. So I'll say kill This process that's running because I can't hit control c and I don't know how to close it So I'll just ask it to kill it Which will send a signal to it. So if I do that and switch back over Oh So screw you again So but now it says screw you for a different reason says ignoring signal 15 If we go back to the slide well 15 was supposed to be sig term, which was the nice way of saying to exit So the intended use of that is like someone really wants me to exit But I should clean up free memory Maybe you know write out files if I need it do some quick cleanup so I can exit safely But There's signals. So you're free to just ignore them and be like, yeah, I don't want to exit right now. I'm good so so You can see there's more of violet options here. So there's that nine, which is sig kill So that sig kill one is a bit more fun So by default kill will just send that 15 which is terminate nicely But you can do kill dash nine. So that will send signal nine to that process And if you've ever heard kill dash nine before that's what it's from And then if I do that Hey I look here and just says killed I get the number that's associated with it. So that's 128 plus nine And it says killed and it's done So you might be asking well What's the difference between them and like well, I could ignore sig term. So What's to stop me to just you know, oops Well, you know They can't stop me I'll ignore that too. So we let's go ahead and try it Smart so The difference between 15 and nine is nine is like no, I'm serious. That's like the kernel you die So you're not allowed to ignore nine and that's defined by the kernel doesn't let you ignore it and There's no default handler because you can't handle it. The default thing is the kernel kills you. Yeah No, so I'm getting an error from that sig action system call So this isn't c preventing me. This is like I got error from that system call So the kernel will not let me do it So dash nine is like you can't ignore it. That's like Immediately die. So that might actually help you if you know, if you have a process that is running wild Well, you can just kill dash nine it and it has no other choice but to stop running So now you know how to actually recover your system. So that's pretty good. So yeah Well, if I just close the terminal Oh, geez. Okay, so let's get rid of this So this might be a bad idea, but let's try it actually Here so let's figure out what my process ID is quick So my process ID is Okay, so that's the process ID of my shell. That's running. So I have that down the other one So here's my shell. That's running And your question is I'm going to execute this thing And I can't kill it. I can't do anything. So you're like instead of killing this I'll kill essentially its parent Okay, so Anyone want to hazard guess what happens when I kill its parent? Yeah Yeah, it should be an orphan process and if it's an orphan process it should get reparented Is it still running? Is it a zombie? No, it shouldn't be so it should stick around so bad things will happen. It's all just be super serious Oh, no such process. Okay, cool Oh, I think that one's mine So let me kill that one Hopefully that's one isn't bad Okay, missed I killed something else by accident. Oh, okay, so it just disappeared from there So my tabs done so that terminal is now no longer there So let's see if it's still running So it's not actually running Which is a bit weird. So I did manage to kill it but I Kind of blew blew my own leg off in the process, but I did kill it But so I don't recommend that you could kill it directly But in that case it works and we'll figure out why that worked later because It wasn't it was probably still running when it got orphaned and it got reparented So it probably should have just continued running and just kind of sat around and you know waited for some more input So something definitely happened to it But we'll we'll get to that later So Well, actually I'll just spoil it now. So that one died because since we killed the parent That's the thing that was actually managing that standard in file descriptor So once we killed the parent, there's nothing else To write to whatever it was reading from standard in so it would say hey There's no more bytes that can come in so it would read zero and then just exit normally So that's why it didn't stick around. So you could write something that does stick around though. Yeah Yeah, if I just opened a file it would just stick around So I kind of blew up my leg. So probably take a bit too long to set that back up again But yeah, it would stick around if it was actually a file All right, any other questions So that was fun. We did some stuff so Any other experiments you didn't kill my machine yet. So that's pretty good So we only like moderately killed it So here's that So, yeah, here was just showing that Kill will send that sig term thing kill dash nine again Is the serious version that the kernel will kill it won't give it an opportunity to respond or whatever It just immediately kills it. So you should use that as a last resort. Yeah I knew someone always asked So the question is can I kill one and say hey, I mean it and I said hey if I kill one, that's really bad So let's make sure we make it to the end of the lecture and we'll end with that because it will probably end the lecture All right So some other quick examples. It's like so most operations you kind of want to do are non-blocking so like read will block and weight will block but If you want something to return immediately while there's non-blocking versions of it So let we'll see how to turn weight into a non-blocking call So if you want it to be a non-blocking call There's an option to weight pid if you want and you give it w no hang. So it just returns instantly so There's some other options if we want to react to changes and we don't have a and we only use non-blocking calls So we have two options if we're not going to sit there and wait for it We can either pull which means we're just going to Try it over and over and over again Or we can get an interrupt which will be connected to signals and will hopefully signals will help us with that So let's look at weight with the polling example and see What's bad with that? So we're going to call weight pid over and over again until the child exits And this is actually how some hardware will behave So if you need to read some data from a device One of the options you might have is just to ask it. Hey, do you have anything for me now? Hey, do you have anything for me now and you keep on asking over and over again like this? And the kernel this would be like actually dealing with hardware And let's see if we run it if we get some type of drawback with that So let's see here's our pull example So in our pull example We're kind of going back to the last lecture quickly. So we start off by forking And then our child will go ahead and sleep for two seconds And then in the other process In our main parent process, we're just going to set up weight pid as being zero, which is invalid And then set up some space for that whatever Weight writes to and then we're going to count how many times we actually pull So Now weight pid will be zero whenever we call weight and a child has not exited yet So we're just going to say well, there's no child that exited yet Just increment count so I can see how many times I go through this loop And then I'll just print out what attempt I'm at And then I'll call weight pid with the pid of my child Give it the address to write some information to and then give it this option that says Just return immediately Like don't block So this will go over and over again and then Of course, we'll have our error checking and then if we break out the loop that means our child Hopefully has exited so we'll check if it's exited and if it does we'll return its value And then if it doesn't we'll just go say we'll just exit from the process that says it's an error and then They'll both exit with zero if they're successful So the child should just sleep for two seconds exit with zero and then the parent should do all this stuff So anyone has to guess how many attempts we might take if we do this approach instead of just calling weight and just laying at weight So let's see how fast our thing actually is Whoops. Oh, right. I killed my you killed my shell. Okay. I'm in the wrong directory So if I do that Turns out it takes a lot of time So I essentially wasted was that like A quarter of million calls by just saying hey you done yet. Hey you done yet. Hey you done yet. Hey you done yet Imagine doing that like 200,000 times. It's pretty annoying So I'm essentially just wasting my time by just asking over and over again. So Anyone have a good idea of what I could do to not waste so much time So what would I do if I didn't want to ask just as fast as I can? Yeah Without using interrupts Yeah, so I could just add a delay so If I wanted to not waste as much time, you know, maybe I just like Sleep for a second So if I go ahead and sleep for a second, I'll be like wait you done yet. Were you done yet? Were you done yet? And then hey, it only took three But now I have kind of the opposite issue where I'm a bit more efficient because I don't waste time checking But I also Was essentially a second late because it died around two seconds and I got it at around three So this becomes like an engineering trade-off where you're trading response time For essentially how much time you're wasting by just asking the question over and over again So the longer you wait between them the worst your response time is going to be but the less time you're going to have wasted So knowing the frequency to actually pull is kind of A choice that you'll have to make Based off how important it is to get a response right away So you can imagine if this was like a game or something and you were like a second behind your friend Well, and that's probably not good Okay, so So the other thing we could do is we could do the interrupt example So remember I kind of said it before that You know when your child dies you'll get poked So that poking is the kernel will actually send you a signal when your child dies And it's given a sig child as the signal number So what we can do is we can say hey, we'll handle that And in that you could just call weight exactly when your child dies and your program can just actually Create that child do whatever do useful things and you don't have to worry about having to Deal with it immediately. You just get interrupted as soon as it's done. You don't have to pull you don't have to do anything And it just works So that really quick And then we'll do something silly So here's the same thing. So I just fork Make sure I don't have an error sleep And then in the main process I just say hey, I'm just going to go to sleep for like 999 seconds I don't care that could actually represent useful work And then in the signal handler I just see hey, do I have sig child if I do I call weight And then if I do I would just immediately react to my child. So if I run that I go to sleep But I get interrupted from a signal and I go ahead wait Immediately and then it's all cleaned up and everything's good to go So that's one way of doing it and I'll wrap up and then I will kill. I'll do something silly Oh, yeah Okay, I'll just I'll fill it in next lecture. All right. So let's do something silly. So there was a question Good question. It's like hey, well if I can kill dash nine something and we know one is really important What happens when I do that? Oh god So kill dash nine one means my init process That's like my orphanage and responsible for doing everything. I'll just kill it and let's see what happens colonel smart So the colonel will not let you kill one because it knows it's important. So let's just be like, no, yeah, I'm rude. I'm fine It so that case nothing else happened and if I look Uh, that doesn't give me a year. But basically the colonel's smarter than you and won't let you kill in it So you can't actually brick your system. Thank goodness because that that would that I could have actually ran this before so you can't kill one but Well, did I kill There's something like 70 no 701 okay, so this was remember when something got reparented it went to this and this was like my system d for my user So if I kill this this should actually kill my user and yeah So I killed my whole thing and essentially made me log in again So if you want to kill your friend system and you can go ahead and do that to their user to their system d So with that just remember pulling for you. We're on this together