Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
ExcessBLarg!
Sep 1, 2001
Edit: Dupe post, whoops!

Adbot
ADBOT LOVES YOU

sarehu
Apr 20, 2007

(call/cc call/cc)
The ability to fork your own process and not exec is nice. What I would want is the ability to safely reload ones own executable fresh from disk but with different command line arguments or a different entry point and an explicit enumeration of file descriptors to keep open. Actually this would be useless because you'd target the lowest common denominator anyway and just spawn a pristine worker process at startup. And heck if you're serializing process arguments you might as well send them over a pipe anyway. So yeah just fork.

ExcessBLarg!
Sep 1, 2001

Suspicious Dish posted:

I would prefer a system where fork(); took a function pointer, the child process inherited all the VM maps from the parent process but were set readonly,
So you'd end up with read-only data segments. That might be tolerable if you can make sure that all subsequent variable modifications are register/stack only. The first thing that comes to mind it breaks is libc errno. Either way, there's an assumption that the goal of the child process to exec, which isn't always the case.

Suspicious Dish posted:

and POSIX specified the mind-blowingly-useless vfork();.
vfork is it's own horror, but that's not really what happened.

Before BSD implemented COW fork, vfork was implemented as an optimization for the common fork-then-exec case to avoid the expense of copying rw pages. Now, if you were chummy with your compiler, you didn't have to immediately exec, but instead could call functions in the child process to set fds, etc., so long as the stack was not modified or unwound above the vfork call--hence, it was still strictly more useful than a spawn (fork-then-immediately-exec). Of course, use of vfork is pretty darn dangerous and not worth the benefit after COW fork came around. It's not clear to me if vfork persisted in its vestigial form in POSIX because vfork-exec was still common in code or because they wanted POSIX to support MMU-less systems. Possibly both.

ExcessBLarg! fucked around with this message at 05:59 on Feb 6, 2015

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
POSIX vfork() is specified that you literally cannot do anything other than immediately exec().

fork() without exec() is really bad and you shouldn't ever do it.

TheresaJayne
Jul 1, 2011
Sounds a little like my first ever hack,

At college they had set /dev/tty root:root -rwx-------- Which meant for less and more to work they had to be Setuid Which meant that will more you could do !csh at the next page prompt and get a Root shell :)

We knew that wouldnt last long so i (not knowing any sourcecode for unix Berkley SysV) worked out how the su command worked and rewrote it with a back door in it.

And would you know - It worked. Except if you did an su then ps -ef showed something like aprofessor (su) csh
this is because we hadn't been taught about fork/exec so i had exec'd the user shell instead of forking it :(

Still they didn't notice until after I left the college.

su - username worked
su worked
su - worked
su username worked
but if after typing su you pressed Ctrl-Y then pressed enter, it would give you root shell and not log that you used Su either :)

Hiowf
Jun 28, 2013

We don't do .DOC in my cave.

LeftistMuslimObama posted:

Yeah, the whole time they were explaining fork and how elegant it was in the lecture, I kinda kept wondering to myself "am I the only person in here who thinks this is really stupid?". Glad to know I'm not alone.

I especially loved the part about how great it is that the child and parent are totally sharing the same memory until they aren't.

Dunning–Kruger effect in action. If you think it's obvious why fork is "really stupid" when it's first explained to you, then it's probably caused by a lack of understanding on your end rather than Ken Thompson and Dennis Ritchie being incompetent.

Spatial
Nov 15, 2007

Someone's got a vfork() up their rear end in a top hat

Less Fat Luke
May 23, 2003

Exciting Lemon

Suspicious Dish posted:

fork() without exec() is really bad and you shouldn't ever do it.
Can you elaborate on that a bit? I'm familiar with both and I'm used to having applications in the Ruby world that generally load an application and fork a bunch of worker processes (because LOL at Ruby threading) but I'm not sure what it means to fork() without exec().

ulmont
Sep 15, 2010

IF I EVER MISS VOTING IN AN ELECTION (EVEN AMERICAN IDOL) ,OR HAVE UNPAID PARKING TICKETS, PLEASE TAKE AWAY MY FRANCHISE

Less Fat Luke posted:

Can you elaborate on that a bit? I'm familiar with both and I'm used to having applications in the Ruby world that generally load an application and fork a bunch of worker processes (because LOL at Ruby threading) but I'm not sure what it means to fork() without exec().
There are some details here:

quote:

The environment in the child process is harsh and makes it difficult to write correct code to run there. Anything you do beyond a direct call to an exec function has to be done with great care. That's why the error handling code is written the way it is.
https://mikeash.com/pyblog/friday-qa-2012-01-20-fork-safety.html

quote:

In my opinion there are so many problems with fork(2) in multi-threaded programs that it's almost impossible to do it right. The only clear case is to call execve(2) in the child process just after fork(2). If you want to do something more, just do it some other way, really. From my experience it's not worth trying to make the fork(2) call save, even with pthread_atfork().
http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them

zergstain
Dec 15, 2005

So when, let's say, Apache fork()s, does it exec() to httpd?

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
No. Apache prefork isn't multithreaded and thus can fork all day long practically worry-free.

zergstain
Dec 15, 2005

Oh, it's only an issue if the parent is multithreaded. Some of the posts made it sound like not quickly exec()ing was always bad.

This all reminds me of my "make a shell" assignment in my OS class, where I was trying out vork() to spawn processes. I was developing on OS X 10.7, and if I attached gdb to the vfork()ed process before exec(), the kernel would panic 100% of the time. So I wrote a small program to exploit that. I have the code, but the bug was patched by 10.8.

My final solution was gently caress vfork()

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
It's also an issue if the parent has any global state. I know of a few libraries that allocate a giant chunk of contiguous memory with mmap() -- when the child forks, that memory isn't copy-on-write, since it's supposed to work like shared memory.

This caused a hard-to-track-down bug with Python's multiprocessing module (which forks w/out exec) and libffi/ctypes (which allocates a giant page with mmap) where customers got various memory corruption.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

Skuto posted:

Dunning–Kruger effect in action. If you think it's obvious why fork is "really stupid" when it's first explained to you, then it's probably caused by a lack of understanding on your end rather than Ken Thompson and Dennis Ritchie being incompetent.

I understand fork() extremely well and still think it's a poor abstraction for many reasons. I don't think there's any part of "the child process inherits all the parent's global state and references to kernel objects" that's particularly sane, because you can easily end up with weird corruption issues if you forget to reset some state.

Bhodi
Dec 9, 2007

Oh, it's just a cat.
Pillbug
Am I safe from this poo poo if I just use default thread / mutex libraries in perl/ruby/python because the thinking has already been done for me? Or is this something I really need to sit down and understand for the future. Because I really hope not.

Hiowf
Jun 28, 2013

We don't do .DOC in my cave.

Suspicious Dish posted:

I understand fork() extremely well and still think it's a poor abstraction for many reasons.

You are preaching to the choir. I'm just pointing out that the issues with it, which you highlighted very well, are actually far from obvious.

Hiowf
Jun 28, 2013

We don't do .DOC in my cave.

Bhodi posted:

Am I safe from this poo poo if I just use default thread / mutex libraries in perl/ruby/python because the thinking has already been done for me? Or is this something I really need to sit down and understand for the future. Because I really hope not.

You don't need to care about this in those languages. These fork issues are fairly low-level and not actually that well understood even by experienced Unix programmers. Even Chrome had bugs with this because they use(d) STL after fork but before exec in their IPC library.

Hiowf
Jun 28, 2013

We don't do .DOC in my cave.

Skuto posted:

Even Chrome had bugs with this because they use(d) STL after fork but before exec in their IPC library.

https://code.google.com/p/chromium/issues/detail?id=36678 (2010)
https://code.google.com/p/chromium/issues/detail?id=179923 (same issue again 3 years later)

1337JiveTurkey
Feb 17, 2005

I'm struggling to see what bizarre set of circumstances where it would make sense to fork() and not exec() in a multithreaded process. It's like I want another independent thread of execution accessing the same resources but I can't use a thread since I also want batshit insane memory semantics to spice things up.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨


That must be amenable to static analysis.

Hiowf
Jun 28, 2013

We don't do .DOC in my cave.

1337JiveTurkey posted:

I'm struggling to see what bizarre set of circumstances where it would make sense to fork() and not exec() in a multithreaded process.

I'm not sure what those would be either, but it's not "fork and not exec", that's causing the bugs, it's "fork and not exec *immediately*". As for the latter, for example Chromium closes off a bunch of FDs in the child processes, and I think you can probably guess why you want to do that.

sarehu
Apr 20, 2007

(call/cc call/cc)

Skuto posted:

Dunning–Kruger effect in action. If you think it's obvious why fork is "really stupid" when it's first explained to you, then it's probably caused by a lack of understanding on your end rather than Ken Thompson and Dennis Ritchie being incompetent.

Regarding being a noob and hearing somebody saying something that makes no sense and thinking "oh there must be some reason why they are right, they surely would know what they are talking about": that's a fallacy that has hit me again and again and again. If there are obvious problems with an idea and the person introducing the idea is not signalling knowledge of objections that people might have, it's a good idea not to give them the benefit of the doubt.

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer
Yeah, I just basically didn't see why fork() is useful by itself, because it seemed like you'd pretty much always need to exec() right afterward.In my mind, a more straightforward way to do it would be to spin off a process using some sort of process constructor syntax where you could pass the child process any data it needs that way, rather than dealing with copy-on-write memory and having code in side of a process that exists just to call another process after the process duplicates itself with fork(). It just seems like for most use cases fork() just adds an extra step to calling another process. Fork() is probably quite lovely if you really do just want a copy of the currently running process, but why fork()+exec() instead of just something like spawnProcess(<function pointer>,<parameters>)?

I'm totally willing to accept that I'm just totally wrong about all of this, but fork() just seems to be extraneous to most of the cases where you'd spawn off another process.

Edison was a dick
Apr 3, 2010

direct current :roboluv: only
Fork is grand as an extensible way to set up the environment before exec. File redirections and pipelines work because of all the descriptor juggling between fork and exec. Same with stuff like dropping capabilities and entering new name spaces.
If you couldn't do this between fork and exec you would need an ever growing CreateProcess syscall or different syscalls for changing the current processes state and changing the state of any new subprocesses you spawn.
Using it for anything that isn't setting up for another exec pretty much requires you to build your whole runtime around the idea.

sarehu
Apr 20, 2007

(call/cc call/cc)
Those are "completely" different because exec is a different thing than calling a function through a function pointer. It is still useful to know that your process's executable has not been replaced, which is why being able to make a process out of yourself without using a file name is good. Maybe you can actually self-exec somehow on the same file on some OSes, even if something else has been moved in its place. But I think spawning a worker process early on to fork pristinely over is a mild inconvenience.

Edison was a dick
Apr 3, 2010

direct current :roboluv: only

sarehu posted:

Maybe you can actually self-exec somehow on the same file on some OSes, even if something else has been moved in its place.

Exec /proc/self/exe maybe.
I know the CRIU guys have found a way to do it, but it might involve reading /proc/self/maps and serialising all the executable pages used by your process.

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer

sarehu posted:

Those are "completely" different because exec is a different thing than calling a function through a function pointer. It is still useful to know that your process's executable has not been replaced, which is why being able to make a process out of yourself without using a file name is good. Maybe you can actually self-exec somehow on the same file on some OSes, even if something else has been moved in its place. But I think spawning a worker process early on to fork pristinely over is a mild inconvenience.

I guess what confuses me, though, is why there isn't a command that's just "Make a new process with this program/function and these arguments and then link it to me as a child". It seems like it would do the same thing as fork()+exec() with fewer lines of code, unless the lecturer for my class simply didn't explain the nuances well at all.

Hiowf
Jun 28, 2013

We don't do .DOC in my cave.

LeftistMuslimObama posted:

Yeah, I just basically didn't see why fork() is useful by itself, because it seemed like you'd pretty much always need to exec() right afterward.

No, you don't. Fork() without exec is the archetypal way to make a multiprocessing server in Unix. And that other thing you disliked (COW) is pretty important for that.

Hiowf
Jun 28, 2013

We don't do .DOC in my cave.

sarehu posted:

the person introducing the idea is not signalling knowledge of objections that people might have, it's a good idea not to give them the benefit of the doubt.

We could've done away with all the security holes from string processing and memory handling in C if we just hadn't given those same guys the benefit of the doubt and stuck with LISP machines.

sarehu
Apr 20, 2007

(call/cc call/cc)

LeftistMuslimObama posted:

I guess what confuses me, though, is why there isn't a command that's just "Make a new process with this program/function and these arguments and then link it to me as a child". It seems like it would do the same thing as fork()+exec() with fewer lines of code, unless the lecturer for my class simply didn't explain the nuances well at all.

If it would do the same thing then you can just define such a function yourself, if saving lines of code is your goal.

Vanadium
Jan 8, 2005

Disabling COW is great because it means big processes can't launch other processes at all

The MUMPSorceress
Jan 6, 2012


^SHTPSTS

Gary’s Answer

Skuto posted:

No, you don't. Fork() without exec is the archetypal way to make a multiprocessing server in Unix. And that other thing you disliked (COW) is pretty important for that.

Cool. It seems like I'm just not getting the whole picture in this class then. Hopefully it's something they plan to circle back to as an advanced topic, rather than just a deficiency in the material covered.

feedmegin
Jul 30, 2008

LeftistMuslimObama posted:

I guess what confuses me, though, is why there isn't a command that's just "Make a new process with this program/function and these arguments and then link it to me as a child". It seems like it would do the same thing as fork()+exec() with fewer lines of code, unless the lecturer for my class simply didn't explain the nuances well at all.

There is, on some Unixen. Google posix_spawn.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

Vanadium posted:

Disabling COW is great because it means big processes can't launch other processes at all

How so?

Karate Bastard
Jul 31, 2007

Soiled Meat
Speaking of LISP, I've been meaning to learn me a functional programming, for evaluation of possible good, but the online materials I've found are kinda quirky and go on at length about trivial stuff in a self-deprecating tone

(this syntax sure is weird huh, it is not what you are used to, ha ha, it's like talking with a ...lisp... *badum-tish* but don't you worry, *wink*, this will all feel natural to you as you quickly become an ~expert LISPER~ , droooone blah blah blather blah, now here is a description of how you unpack nested return values only we call it "pattern matching" like no sensible people would, and we go on for pages about it)

like a prolonged windup to the real subject matter, which never comes, but instead they're like "welp now you know basic syntax good luck here's a link to the STL bye now". So yeah, I actually do want to collectively call them a horror, because none of this functional programming stuff is really that hard, and this tiptoeing around it just paints it weird. I just want a resource that hits me in the face with it, like the go tour. Here, this is how you make a list. Here is how you pass it to a function. Here is map, here is reduce. Here is how you load a chunk of structured data and this is how you write it to disk, in various formats. Here's a realistic example that solves a common problem, so that you can compare performance with whatever you can hack together in your favorite language. This is how you write idiomatic code in this language.

And yes, this goes for that goon haskell site as well *throws glove* and no, I don't want a paper book about programming.

This is where you get to call me an idiot and prove me wrong by fulfilling my needs.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Karate Bastard posted:

and no, I don't want a paper book about programming.

SICP is available online.

VikingofRock
Aug 24, 2008




Karate Bastard posted:

Speaking of LISP, I've been meaning to learn me a functional programming

I really liked Real World Haskell, although I'll occasionally use Learn You A Haskell as a reference (for those sections where he lists a bunch of useful functions relating to something). It's not a perfect book but I learned a ton from it.

quote:

now here is a description of how you unpack nested return values only we call it "pattern matching" like no sensible people would

Also everyone calls it pattern matching.

Karate Bastard
Jul 31, 2007

Soiled Meat
Thanks for the tips you guys!

VikingofRock posted:

Also everyone calls it pattern matching.

They do? Is this a lisp thing, because I've only ever heard it in connection to string parsing, like globbing and regexes and the like?

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

Karate Bastard posted:

They do? Is this a lisp thing, because I've only ever heard it in connection to string parsing, like globbing and regexes and the like?

It's a "thing" in languages that provide actual pattern matching functionality.

I'm going to take a stab that the reason you referred to it as "unpacking nested return values" is because you saw something like:
code:
(a, b) <- zip as bs
And saw that it looked pretty similar to, say,
Python code:
x, y = zip(xs, ys)
And you'd kind of be right! The real difference here is that pattern matching in Haskell (and other functional languages) is much more powerful, and unpacking the result of a function call is only one example of what it can be used for. For example, in Haskell you can do something like:

code:
take 0 _ = []
take _ [] = []
take n (x:xs) = x : take (n-1) xs
Instead of simply binding the arguments to names and then testing them as you would in an imperative language, you can pattern match for special cases that need to be handled separately, and then not worry about them in the definition of the general case.

Adbot
ADBOT LOVES YOU

nielsm
Jun 1, 2009



In functional languages, any construct that lets you compare a value against several different, partially or fully filled out structures, with optional placeholders for capturing partial contents, is called a pattern matching construct.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply