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
suffix
Jul 27, 2013

Wheeee!

Soricidus posted:

for how long did you think anything else?

there's "this is a terrible idea that will lead to unintended consequences" bad, and there's "this breaks the interface contract, can lead to broken states, and should be fixed even at the cost of backwards compatibility" bad

sure, equals/hashCode breakage happens all the time in badly written third-party code but it shouldn't happen in the standard library imo

i did a little testing, and this leads to duplicate items in hashmaps, but not of the exact same item since the hash code is cached.


test code:
Java code:
import java.net.InetAddress;
import java.net.URL;
import java.util.HashSet;

class TestUrl {
	public static boolean canConnect(String addr) {
		try {
			InetAddress.getByName(addr);
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	public static void main(String[] args) throws Exception {
		String addr = "http://www.example.org";
		URL url1 = new URL(addr);
		URL url2 = new URL(addr);

		System.out.println("Connected: " + canConnect(url1.getHost()));

		HashSet<URL> url_set = new HashSet<>();
		url_set.add(url1);

		System.out.println("disconnect from network, wait 30 seconds and press enter");
		System.in.read();

		System.out.println("Connected: " + canConnect(url1.getHost()));
		System.out.println("url1 and url2 are equal: " + url1.equals(url2));
		System.out.println("but url_set does not contain url2: " + url_set.contains(url2));
		System.out.println("since they have different hash codes: " + url1.hashCode() + "!=" + url2.hashCode());
		url_set.add(url2);
		System.out.println("so we can have both in the same set: " + url_set);
	}
}
outputs:
code:
Connected: true
disconnect from network, wait 30 seconds and press enter

Connected: false
url1 and url2 are equal: true
but url_set does not contain url2: false
since they have different hash codes: 1575608655!=-1875064991
so we can have both in the same set: [[url]http://www.example.org,[/url] [url]http://www.example.org[/url]]

Adbot
ADBOT LOVES YOU

Brain Candy
May 18, 2006

suffix posted:

there's "this is a terrible idea that will lead to unintended consequences" bad, and there's "this breaks the interface contract, can lead to broken states, and should be fixed even at the cost of backwards compatibility" bad

this worked so nicely for python3 and perl6

or you u could use URI you baby

Shaggar
Apr 26, 2006

suffix posted:

there's "this is a terrible idea that will lead to unintended consequences" bad, and there's "this breaks the interface contract, can lead to broken states, and should be fixed even at the cost of backwards compatibility" bad

sure, equals/hashCode breakage happens all the time in badly written third-party code but it shouldn't happen in the standard library imo

i did a little testing, and this leads to duplicate items in hashmaps, but not of the exact same item since the hash code is cached.


test code:
Java code:
import java.net.InetAddress;
import java.net.URL;
import java.util.HashSet;

class TestUrl {
	public static boolean canConnect(String addr) {
		try {
			InetAddress.getByName(addr);
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	public static void main(String[] args) throws Exception {
		String addr = "http://www.example.org";
		URL url1 = new URL(addr);
		URL url2 = new URL(addr);

		System.out.println("Connected: " + canConnect(url1.getHost()));

		HashSet<URL> url_set = new HashSet<>();
		url_set.add(url1);

		System.out.println("disconnect from network, wait 30 seconds and press enter");
		System.in.read();

		System.out.println("Connected: " + canConnect(url1.getHost()));
		System.out.println("url1 and url2 are equal: " + url1.equals(url2));
		System.out.println("but url_set does not contain url2: " + url_set.contains(url2));
		System.out.println("since they have different hash codes: " + url1.hashCode() + "!=" + url2.hashCode());
		url_set.add(url2);
		System.out.println("so we can have both in the same set: " + url_set);
	}
}
outputs:
code:
Connected: true
disconnect from network, wait 30 seconds and press enter

Connected: false
url1 and url2 are equal: true
but url_set does not contain url2: false
since they have different hash codes: 1575608655!=-1875064991
so we can have both in the same set: [[url]http://www.example.org,[/url] [url]http://www.example.org[/url]]

url should be marked as deprecated

Shaggar
Apr 26, 2006

akadajet posted:

http://builtwithember.io/

Much better. Even has one of those trendy .io domains.



edit: lmao! sorry shaggar.


I have heard of all those identical base-template-looking emberjs sites, but idk who dell or godaddy are.

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder

akadajet posted:

it's like, angular's headliner product.
https://builtwith.angularjs.org/


Hahaha.

I didn't use it much because it was unusable

I don't think that's really a horror though. Why are they using a client oriented js to build what should be a native app.?

Shaggar
Apr 26, 2006
because ~web "developers"~

Sapozhnik
Jan 2, 2005

Nap Ghost
wonder if i can bait him into a probation-by-Silverlight-post

Condiv
May 7, 2008

Sorry to undo the effort of paying a domestic abuser $10 to own this poster, but I am going to lose my dang mind if I keep seeing multiple posters who appear to be Baloogan.

With love,
a mod


MALE SHOEGAZE posted:

Hahaha.

I didn't use it much because it was unusable

I don't think that's really a horror though. Why are they using a client oriented js to build what should be a native app.?

i was wondering why ps3 youtube was so goddamn slow

Pie Colony
Dec 8, 2006
I AM SUCH A FUCKUP THAT I CAN'T EVEN POST IN AN E/N THREAD I STARTED
can we talk about erlang error messages for a second?

code:
{"init terminating in do_boot",{rabbit,failure_during_boot,{could_not_start,rabbit,{bad_return,{{rabbit,start,[normal,[]]},{'EXIT',{rabbit,failure_during_boot,{error,{badarg,[{erlang,bit_size,["password"],[]},{rabbit_auth_backend_internal,salted_md5,2,[{file,"src/rabbit_auth_backend_internal.erl"},{line,216}]},{rabbit_auth_backend_internal,hash_password,1,[{file,"src/rabbit_auth_backend_internal.erl"},{line,202}]},{rabbit_auth_backend_internal,'-add_user/2-fun-0-',2,[{file,"src/rabbit_auth_backend_internal.erl"},{line,156}]},{mnesia_tm,apply_fun,3,[{file,"mnesia_tm.erl"},{line,832}]},{mnesia_tm,execute_transaction,5,[{file,"mnesia_tm.erl"},{line,812}]},{rabbit_misc,'-execute_mnesia_transaction/1-fun-0-',1,[{file,"src/rabbit_misc.erl"},{line,497}]},{worker_pool_worker,handle_call,3,[{file,"src/worker_pool_worker.erl"},{line,92}]}]}}}}}}}}}
they are completely unreadable

code:
{error_logger,{{2014,10,29},{4,5,39}},crash_report,[[{initial_call,{net_kernel,init,['Argument__1']}},{pid,<0.21.0>},{registered_name,[]},{error_info,{exit,{error,badarg},[{gen_server,init_it,6,[{file,"gen_server.erl"},{line,320}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]}},{ancestors,[net_sup,kernel_sup,<0.10.0>]},{messages,[]},{links,[<0.18.0>]},{dictionary,[{longnames,true}]},{trap_exit,true},{status,running},{heap_size,987},{stack_size,27},{reductions,675}],[]]}
{error_logger,{{2014,10,29},{4,5,39}},supervisor_report,[{supervisor,{local,net_sup}},{errorContext,start_error},{reason,{'EXIT',nodistribution}},{offender,[{pid,undefined},{name,net_kernel},{mfargs,{net_kernel,start_link,[['rabbitmqctl298@',longnames]]}},{restart_type,permanent},{shutdown,2000},{child_type,worker}]}]}
{error_logger,{{2014,10,29},{4,5,39}},supervisor_report,[{supervisor,{local,kernel_sup}},{errorContext,start_error},{reason,{shutdown,{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}}},{offender,[{pid,undefined},{name,net_sup},{mfargs,{erl_distribution,start_link,[]}},{restart_type,permanent},{shutdown,infinity},{child_type,supervisor}]}]}
{error_logger,{{2014,10,29},{4,5,39}},crash_report,[[{initial_call,{application_master,init,['Argument__1','Argument__2','Argument__3','Argument__4']}},{pid,<0.9.0>},{registered_name,[]},{error_info,{exit,{{shutdown,{failed_to_start_child,net_sup,{shutdown,{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}}}},{kernel,start,[normal,[]]}},[{application_master,init,4,[{file,"application_master.erl"},{line,133}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,239}]}]}},{ancestors,[<0.8.0>]},{messages,[{'EXIT',<0.10.0>,normal}]},{links,[<0.8.0>,<0.7.0>]},{dictionary,[]},{trap_exit,true},{status,running},{heap_size,376},{stack_size,27},{reductions,117}],[]]}
{error_logger,{{2014,10,29},{4,5,39}},std_info,[{application,kernel},{exited,{{shutdown,{failed_to_start_child,net_sup,{shutdown,{failed_to_start_child,net_kernel,{'EXIT',nodistribution}}}}},{kernel,start,[normal,[]]}}},{type,permanent}]}
maybe it's because i don't know erlang (but probably not)

more like dICK
Feb 15, 2010

This is inevitable.
It's a formatted stack trace. What's not to understand about it?

Pie Colony
Dec 8, 2006
I AM SUCH A FUCKUP THAT I CAN'T EVEN POST IN AN E/N THREAD I STARTED
maybe if it was actually formatted with indentation and line breaks it would be better, but not by much

MononcQc
May 29, 2007

Pie Colony posted:

maybe if it was actually formatted with indentation and line breaks it would be better, but not by much

If it was formatted that way, it'd confuse a bunch of line-based loggers, I believe. The default error logger shipping with Erlang prints it formatted, but lager (which you likely use here indirectly) forces them on a single line.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Malcolm XML posted:

yeah i mean NT itself ("native") can fork processes and poo poo "{Nt,Zw}CreateProcess" <-- maybe

but win32 has some hangup w.r.t message pumping and the like afaict

ok, it's been a while since last time I did this. here we go

superficially, it may look like win32 has almost everything needed to implement the UNIX core APIs except for a low-level fork primitive that creates a copy on write duplicate of the calling process. handles are pretty much the same thing as file descriptors, and everything revolves around handles and objects just like everything in unix revolves around file descriptors

let's see how win32 could implement a hypothetical CloneProcess function. a rough outline of what CreateProcess does:

  • locates the executable file
  • opens the executable
  • parses it as a PE or PE+ executable. this is the point where CreateProcess will gently caress off and hand out the executable to an emulator (ntvdm, wow, wow64, posix subsystem...) if it's not a win32 executable of the right architecture, or run it with cmd /c if it has an unkown format and its extension is .bat or .cmd
  • a gigantic mess of policy checking to see if the executable should run according to the Safer service, a pretty sweet rule-based execution policy system that I think is very underused
  • creates the process with NtCreateProcess
  • writes the PPB (process parameter block) to the process, containing the command line, environment, standard handles, etc.
  • allocates the main thread's stack
  • sets up the main thread to start executing in an internal "start of process" function, which wraps the executable's entry point
  • creates the main thread with NtCreateThread

CloneProcess looks pretty simple to implement:

  • calls NtCreateProcess with a NULL executable, which means "clone the parent process"
  • captures the current thread's registers and stack limits
  • clones the current thread in the child process with NtCreateThread, passing the captured registers and stack limits. registers are changed so that the cloned thread can tell it's the clone

so easy! so straightforward! so broken! you may or you may not realize that the clone process is created with an empty handle table, except for the inheritable handles. all file handles (and other handles) are now invalid, the clone process is useless. making a handle inheritable is equivalent to clearing FD_CLOEXEC for a file descriptor, which is all fine and well since CreateProcess is a fork+exec equivalent and inheritable handles is what you need for that, but totally useless in the case where fork essentially behaves like exec. how do we clone the handle table, inheritable and non-inheritable handles alike? well, we can't, there is no way. except by deep, undocumented kernel fuckery, of course. DuplicateHandle in a loop would work, if it made any guarantee of giving the duplicate handle the same value (it doesn't)

let's say we do resort to deep, undocumented kernel fuckery. we now have perfect duplicates of the original handles, with the same values and referring to the same objects. again, this is broken. file objects (most common object type after events, iirc) behave in a subtly different way from UNIX file descriptors. while multiple handle can refer to the same object, one file number refers to one file descriptor, no exceptions: duplicating a file descriptor doesn't create a new reference to the same descriptor like duplicating a handle does. multiple handles to the same file object compete for access to the same data, like the current read/write position and the synchronous I/O lock: we have created a mechanism to generate interesting deadlocks at best, or data corrupting race conditions at worst. we'd have to special case file objects, instead of duplicating their handles we'll outright reopen them (... and copy over metadata like the aforementioned current r/w position), and use even more fuckery to ensure the reopened files have the same handle values as the the originals

assume we made it so far. still broken. reopening a pipe doesn't give us an independent descriptor of the same pipe, it tries to reconnect to the pipe, which is fine if the pipe is something like a RPC client end (if not for the fact that it will completely misalign the actual state of the connection with the state expected by the client code), but will outright fail for anonymous pipes, which are created with a connection limit of 1. god knows what happens with other very special files like sockets. these special files are probably safer to just duplicate instead of reopen

ok, assume we successfully special-cased for pipes, sockets and the like (may not be actually possible). broken again. there's a very important object type that really, really doesn't like being shared across processes: they're called LPC (local procedure call) ports, and they're the single most important IPC mechanism in all of windows. nearly all built-in windows services use them as an RPC transport, and out-of-process COM components are invoked through them. some win32 APIs are secretly based on RPC calls. all of these things automatically stop working in the cloned process, or at the very least all current connections are interrupted (I don't know if the RPC client even has reconnection logic for LPC ports considering they're never supposed to disconnect)

let's be optimistic, and assume that all RPC clients are well behaved and eventually reconnect (may not be true). well I hope you weren't using windows in your parent process, because the cloned process is going to be boarded up like a cellar in a storm. all window handles are now automatically invalid, because there's no way to duplicate windows, and even if there was, window handles share a namespace across all processes in the same session. nominally, the handles are still valid, but the windows are owned by the parent process: you can send messages to them, but not receive messages sent to them. maybe you think you don't have any windows in your process, but you'd be surprised, a lot of libraries create hidden windows to receive broadcasts or implement per-session IPC protocols. in fact I think OLE itself creates hidden message-only windows when you run an OLE message loop. all of these things stop working in the cloned process. again a lot of APIs and libraries may use hidden windows or OLE and you have no way of knowing

ok, let's speculate wildly. let's say we define a new notification for DllMain, something like DLL_PROCESS_BEFORE_CLONE and DLL_PROCESS_AFTER_CLONE that would work like pthread_atfork. let's say all core system libraries use these notifications to properly clone their state to the child process (the simplest implementation would be to simply mark all state invalid, and reinitialize on first use, to add the least overhead to CloneProcess). let's say that we document the limitations this imposes on what you can do in a cloned process (like doing UI work). a regular, honest, blue-collar command line program will do just fine! it will be, after all, the most common use case for CloneProcess, and we only have to ensure that things like console I/O still work

CloneProcess breaks console I/O specifically. in win32, consoles are not I/O devices. sure you open handles to them, you pass them to ReadFile and WriteFile, but a few things should have tipped you off that they are impostors. for one, console input handles are waitable: sure file/device handles are waitable, but they are signaled when a I/O operation completes, not when data is available to read. that select/poll-like behavior is unique to console input handles handles (in fact there is no select/poll primitive: you use select/WSAPoll for sockets, wait primitives for console input handles and redesign for asynchronous I/O for everything else). consoles are odd values, while actual handles are multiples of 4 (the lowest two bits are reserved as tag bits). so maybe consoles are of a special object type and their handles are tagged to save a roundtrip to kernel mode? no, consoles are an entirely user mode thing. all console APIs are actually RPC calls; when you pass a console handle to WriteFile, WriteFile punts to WriteConsoleA; when you pass a console handle to WaitForSingleObject, it's replaced with a handle to an event that's signaled when input is available; and so on. the implementation of consoles is not just any service, it's a critical system service that among other things implements the few win32 functionality that doesn't belong in kernel mode (initially: all of it. since NT 4: very little). of all the things that should have been implemented in kernel mode, consoles would top my list, but Microsoft thinks differently. whatever

so what, just connect to this service (basesrv - "base" is the internal codename for win32 - running in csrss.exe - client-server runtime subsystem, once supposed to be the cornerstone of the NT microkernel which never was), ask to inherit the parent's console. can't be done, because we weren't registered as a win32 process. yeah, I lied, CreateProcess does one more thing, which is calling to basesrv to register the newly created process and thread. basesrv will reject any calls that don't come from a currently registered process (LPC ports reliably notify servers of the client's process and thread ids; throughout NT, the process id/thread id tuple is called a "client id", again something that was supposed to be far more important had NT actually been implemented as a microkernel), so this is a mandatory step. CloneProcess keeps getting fatter and fatter: while a lot of state cloning operations can be simply delayed for when the related feature is actually used, registering the clone process and thread is pretty much mandatory. still, not much more overhead than CreateThread, which is the point of a fork function

speaking of threads. have you ever wondered what's inside user mode mutexes, i.e. RTL_CRITICAL_SECTION? it's by no means mandatory, but a mutex should ensure that only its current owner can release it. sure, properly written code will never do otherwise, but it's a nice feature to have, and as it turns out, RTL_CRITICAL_SECTIONs do keep track of the current owner. the current owner is identified by its thread id. the cloned thread has a different id (thread ids are globally unique, in fact they come from the same global handle table as process ids; this wouldn't be necessary if all thread manipulating APIs required both a thread and process id - i.e. the full client id - but that ship has sailed), so it won't be the owner of the cloned critical sections (oh and, luckily critical sections no longer contain a wait queue handle, or the cloned critical sections would share the wait queue with the original critical sections). the cloned thread won't be able to release locks it's supposed to own, and will deadlock when trying to re-acquire them. luckily, for easier debugging, critical sections are all listed in a process-wide doubly-linked list, so we can fix them in the cloned process (more overhead). we could redesign critical sections so that the owner is identified by some per-thread value that carries over to the clone, like the stack base address. the stack base address sadly is unusable, because it can change if the thread is used to run fibers. we could use the TEB, a large amalgamation of all sorts of internal thread-specific data (like the TLS values for the thread, or a copy of the thread id), but the clone thread is in no way guaranteed to have the same TEB address

in fact, speaking of the TEB: we forgot to copy the TEB of the original thread to the clone's. we can't just copy everything over either, things like the thread id should obviously not be overwritten. the TEB is also extremely dense and complicated, and shared between a dozen components. it even contains interior pointers that refer to other parts of itself, which should be fixed up in the clone. and god help you if someone is keeping a pointer to some TEB field because that poo poo will break too. also pray that you aren't calling CloneProcess inside of some system function that uses the TEB, because when you return to that code, it may refer to the old TEB (which may or may not carry over to the cloned address space, I don't know). I don't know if the PEB (like the TEB, but for the whole process) is clone automatically either, it probably isn't and we'll have even more work to do

assuming we fix all users of the TEB to avoid clone-unsafe operations, we can store some kind of local thread id in the TEB, just some integer incremented for every new thread, with the last value stored in some global variable that will be cloned with the address space, and use that as the owner of critical sections, so that we won't have to fix them up

so, after a massive review of an ancient codebase with 30 years of legacy, we have at best a niche, semi-reliable API with an uneasy trade-off between massive overhead, worse than CreateThread and possibly even CreateProcess, and delayed reinitialization, with its associated out-of-context failures

this is all going mostly from memory and I'm sure I'm missing even more problems, but you get the idea. fork for win32 is never going to happen

... by the way, CloneProcess only clones the calling thread, what about all those worker threads secretly spawned by third party libraries, that will now stop working in confusing ways? all DLLs will have to implement DLL_PROCESS_BEFORE_CLONE and DLL_PROCESS_AFTER_CLONE, because there is no high level construct that unequivocally identifies a worker thread as such. also hope that nobody is keeping process and thread ids cached somewhere!

e: oh, actually I didn't answer re. message pumping. the cloned thread is going to have no message queue, which isn't that terrible as they are automatically created on demand. much worse is if you called CloneProcess while inside the message pump, which is altogether a very easy situation to get yourself into. user32 is probably not going to like that the entire message queue disappeared from under its rear end. oh and of course if you lose the message queue, you lose all the messages and this could cause deadlocks if you were waiting for them. non-window messages could be cloned I guess, but messages meant for internal hidden windows are going to be lost this way. it's all very delicate

hackbunny fucked around with this message at 19:09 on Oct 30, 2014

Notorious b.s.d.
Jan 25, 2003

by Reene
so how the gently caress does cygwin work at all in such a hostile environment?

is it all fuckery with threads pretending to be processes?

Shaggar
Apr 26, 2006
is there any actual reason to want to clone a process like that?

also cygwin exists to solve a problem that doesn't exist on windows.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Notorious b.s.d. posted:

so how the gently caress does cygwin work at all in such a hostile environment?

is it all fuckery with threads pretending to be processes?

cygwin fork is a gigantic hack, they actually documented what went into it but I can't remember the details

cygwin has a huge advantage though, in that user applications and libraries by and large don't use Win32 directly, so their "kernel" layer can insulate user code from almost all of this mess. also they don't attempt in any way to fork Win32 state iirc, at the Win32 layer the child process is a regular process, they just copy over stuff from the parent process into it

tef
May 30, 2004

-> some l-system crap ->
how did http://en.wikipedia.org/wiki/Windows_Services_for_UNIX work? or UWIN ?

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Shaggar posted:

is there any actual reason to want to clone a process like that?

not really because with threads and without exec, fork is pointless. you can do cute things like "going in background" in a console program, where you return to the shell while the program keeps running in background, but that's it

exec is the main use case of fork: you fork, set up things in the child process (kernel things, like base priority, security token and so on) and then you exec to reinitialize the process from scratch with a new executable program and command line. that's why fork/exec has so few arguments and CreateProcess so many and so many variants (like CreateProcessAsUser): fork lets you make your own process creation options basically. it's like what I said about using objective c blocks to wrap existing code instead of refactoring everything into an operation packet that you submit and process: being able to pass code around, instead of packets, is so incredibly flexible

let's call the Win32 exec ReCreateProcess. let's say the parent process creates a lot of children, always setting their stdin/stdout. now, the only way to pass stdin/stdout to a child process is by passing inheritable handles. but if you have two concurrent child process creations, both processes will get all currently inheritable handles, not just the ones meant for them!

so. instead of calling CreateProcess, we change the parent process to use CloneProcess. in the clone, we use DuplicateHandle to make inheritable duplicates of the stdin/stdout handles to pass to the child process. we pass the inheritable duplicates to ReCreateProcess (which we can assume takes a STARTUPINFO argument, like CreateProcess). the clone process turns into a proper child process, running the program passed to ReCreateProcess with a new command line and the specified stdin/stdout handles

another example: sanitizing environment variables. sure, you can make a copy of the current environment, and then gently caress with it to remove the offending variables, and pass the sanitized copy to CreateProcess. or you can use CloneProcess, sanitize the environment with regular GetEnvironmentVariable/SetEnvironmentVariable calls, and then call ReCreateProcess (which we can assume takes a lpEnvironment argument, that we'll set to NULL to mean "inherit current environment") to run the program with the sanitized environment

also: in some applications, separate address spaces for threads are very useful, to ensure they can't easily corrupt each other's state

fork/exec is a very flexible mechanism

Shaggar
Apr 26, 2006
fork/exec sounds like dumb Linux crap and a bad idea.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

easy: no Win32 to worry about. Interix programs are run as clean, pure POSIX programs, with no Win32 dlls needed or supported, just ntdll.dll (which hates cloned processes and doesn't even attempt to do things like fix up critical sections; in fact it creates a new main heap and loader lock altogether). if you wanted Win32 functions on Interix you'd have to, like, port Wine to it

to interact with the Win32 world somewhat, they have Win32 launchers (posix.exe) on one side, and on the other, Interix is a microkernel where all system calls are LPC calls to a subsystem process (psxss.exe), which is a regular Win32 program. very important because things like winsock require Win32 (in fact, the original Microsoft-provided POSIX subsystem didn't have sockets and it was useless and garbage). at least, this was Interix 1

in Interix 2 and later, they moved a lot of system calls to client-side posix.dll (which previously only contained libc and LPC stubs), especially things like I/O, if they could be implemented entirely in terms of NT system calls; this massively improved performance for things like, say, read or write which didn't affect global state or involved security checks. they also improved psxss.exe to better interact with Win32, in particular things like mapping Win32 consoles to POSIX ttys. also they ported gcc and binutils so that you could have abominable frankenstein mostrosities of executables that were PE on the outside and old school COFF on the inside, with modern amenities like dynamic loader support and GOT relocations (Windows DLLs are not exactly the same thing as UNIX shared objects, so they added UNIX shared objects to Windows)

in Interix 3 they introduced mixed programs, where you could use both Win32 and POSIX APIs in the same program (apparently the use case for this was using Oracle's client DLL; similar bending over backwards for Oracle can be observed in ADO.NET). to sidestep all the known issues with this setup, mixed programs were compiled and run as Win32 programs that could call Interix system calls if necessary, and they were barred from using fork

tef posted:

or UWIN ?

no idea. never used UWIN or MKS

Dessert Rose
May 17, 2004

awoken in control of a lucid deep dream...

Shaggar posted:

fork/exec sounds like dumb Linux crap and a bad idea.

shaggar getting swept away by the tsunami of actual windows internal knowledge being poured into this thread

kitten emergency
Jan 13, 2008

get meow this wack-ass crystal prison
posts like that make me amazed that windows not only functions, but functions so well that our world literally relies on it

akadajet
Sep 14, 2003

you can tell i'm a webdev i can't comprehend most of hackbunny's posts

pseudorandom name
May 6, 2007

meanwhile, the Austin group has realized that fork is incompatible with threads and has amended the spec to make fork async-signal-unsafe and forbid the use of any async-signal-unsafe functions in the child after a fork

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

uncurable mlady posted:

posts like that make me amazed that windows not only functions, but functions so well that our world literally relies on it

to be fair to win32, CloneProcess was just a thought experiment where we stressed its assumptions pretty hard: when all you have is fork+exec, of course you're going to build over that and pile more and more code over the years that assumes that a new process always starts from a clean slate

but yeah, it's not an elegant design by any stretch. still better than 80s relic VMM (Virtual Machine Monitor, the Windows 9x kernel) e: Virtual Machine Manager oh god I'm such a fraud :ohdear:

pseudorandom name posted:

meanwhile, the Austin group has realized that fork is incompatible with threads and has amended the spec to make fork async-signal-unsafe and forbid the use of any async-signal-unsafe functions in the child after a fork

:monocle: of course

hackbunny fucked around with this message at 10:20 on Oct 31, 2014

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av
lmao Reporter field

Soricidus
Oct 21, 2010
freedom-hating statist shill

hackbunny posted:

lmao Reporter field

you can't really blame a guy for being passionate about ornithology

karms
Jan 22, 2006

by Nyc_Tattoo
Yam Slacker

akadajet posted:

you can tell i'm a webdev i can't comprehend most of hackbunny's posts

prefect
Sep 11, 2001

No one, Woodhouse.
No one.




Dead Man’s Band

hackbunny posted:

but yeah, it's not an elegant design by any stretch. still better than 80s relic VMM (Virtual Machine Monitor, the Windows 9x kernel) e: Virtual Machine Manager oh god I'm such a fraud :ohdear:

"virtual machine manager" is now a thing that's used to manage hyper-v vms

Cybernetic Vermin
Apr 18, 2005

really sort of weird that microsoft had such a slow start at enterprise virtualization, since they did legit do more software virtualization work earlier than anyone else. all very special-purpose, but still recognizably the right sort of thing

Notorious b.s.d.
Jan 25, 2003

by Reene

hackbunny posted:

cygwin fork is a gigantic hack, they actually documented what went into it but I can't remember the details

cygwin has a huge advantage though, in that user applications and libraries by and large don't use Win32 directly, so their "kernel" layer can insulate user code from almost all of this mess. also they don't attempt in any way to fork Win32 state iirc, at the Win32 layer the child process is a regular process, they just copy over stuff from the parent process into it

they have FAQs and it is pretty nasty

https://www.cygwin.com/faq.html#faq.api.fork

quote:

Cygwin fork() essentially works like a non-copy on write version of fork() (like old Unix versions used to do). Because of this it can be a little slow. In most cases, you are better off using the spawn family of calls if possible.

Here's how it works:

Parent initializes a space in the Cygwin process table for child. Parent creates child suspended using Win32 CreateProcess call, giving the same path it was invoked with itself. Parent calls setjmp to save its own context and then sets a pointer to this in the Cygwin shared memory area (shared among all Cygwin tasks). Parent fills in the child's .data and .bss subsections by copying from its own address space into the suspended child's address space. Parent then starts the child. Parent waits on mutex for child to get to safe point. Child starts and discovers if has been forked and then longjumps using the saved jump buffer. Child sets mutex parent is waiting on and then blocks on another mutex waiting for parent to fill in its stack and heap. Parent notices child is in safe area, copies stack and heap from itself into child, releases the mutex the child is waiting on and returns from the fork call. Child wakes from blocking on mutex, recreates any mmapped areas passed to it via shared area and then returns from fork itself.

the exec implementation is even worse. apparently exec is impossible on windows so cygwin tracks fake PIDs to provide the illusion of continuity

https://cygwin.com/cygwin-ug-net/highlights.html

quote:

However, spawn and exec present their own set of difficulties. Because there is no way to do an actual exec under Win32, Cygwin has to invent its own Process IDs (PIDs). As a result, when a process performs multiple exec calls, there will be multiple Windows PIDs associated with a single Cygwin PID. In some cases, stubs of each of these Win32 processes may linger, waiting for their exec'd Cygwin process to exit.

there is lots of "fun" stuff in the highlights document i'm not going to quote the whole thing

Bloody
Mar 3, 2013

dont use fork

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Notorious b.s.d. posted:

the exec implementation is even worse. apparently exec is impossible on windows so cygwin tracks fake PIDs to provide the illusion of continuity

Interix does this too. run Interix ps, and you'll see that all Interix processes have odd pids. as we have learned:

  • handles have two spare tag bits
  • pids are allocated from a global handle table
  • therefore, all pids are multiples of 4

so, Interix has a virtualized process table

hackbunny fucked around with this message at 16:50 on Oct 31, 2014

Malcolm XML
Aug 8, 2009

I always knew it would end like this.

hackbunny posted:

Interix does this too. run Interix ps, and you'll see that all Interix processes have odd pids. as we have learned:

  • handles have two spare tag bits
  • pids are allocated from a global handle table
  • therefore, all pids are multiples of 4

so, Interix has a virtualized process table

interix was a clusterfuck


btw hackbunny have u considered writing for the Windows Internals people?

Malcolm XML
Aug 8, 2009

I always knew it would end like this.

prefect posted:

"virtual machine manager" is now a thing that's used to manage hyper-v vms


I guess but it's a totally different codebase

Notorious b.s.d. posted:

so how the gently caress does cygwin work at all in such a hostile environment?

is it all fuckery with threads pretending to be processes?

this is how that one ksh for windows works

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Malcolm XML posted:

interix was a clusterfuck

still the best UNIX implementation for Windows ever. they even ported Gentoo to it IIRC

Malcolm XML posted:

btw hackbunny have u considered writing for the Windows Internals people?

I have, and I guess alex ionescu could even vouch for me, but

  • I don't feel like an "expert", it's more like a persistent strain of itchy herpes. I write all of my posts 99% from memory, I literally can't forget this stuff
  • I'm not rigorous nor an expert on OS design/development, more of an excitable fangirl. I'm in awe at actual experts like Russinovich or (leaving the field of operating systems) MononcQc, tef, etc. (talk prolog to me tef :wink:)
  • my field of expertise looks broad but really is restricted to "implementing UNIX on Windows 2000", which becomes less and less relevant as years pass (in fact I haven't done any Windows development since 2007 or so)

maybe it's the underachiever speaking, but these are "amateur computer historian" credentials which at best entitle me to give talks in a silly hat*

prefect
Sep 11, 2001

No one, Woodhouse.
No one.




Dead Man’s Band

Malcolm XML posted:

I guess but it's a totally different codebase

i just wanted to contribute some low-value trivia to the discussion :shobon:

tef
May 30, 2004

-> some l-system crap ->

hackbunny posted:

I don't feel like an "expert", it's more like a persistent strain of itchy herpes. I write all of my posts 99% from memory, I literally can't forget this stuff

same, and most of the time i can't remember what day of the week or what date it is. i also get left and right mixed up.

quote:

[*]I'm not rigorous nor an expert on OS design/development, more of an excitable fangirl. I'm in awe at actual experts like Russinovich or (leaving the field of operating systems) MononcQc, tef, etc. (talk prolog to me tef :wink:)

i'm just a database janitor, i have no formal qualifications, i only did two years of computer science etc.

i have read a lot of papers though and people think that counts, but i haven't really written anything or given any advice that i myself did not read or learn from another.

i only became a full time programmer by accident, and almost every job bar one i've gotten was through referrals :v:

i started in computer security and family stuff meant i had to move and get a new job and i ended up writing screen scrapers, and it was all downhill from there.

quote:

maybe it's the underachiever speaking, but these are "amateur computer historian" credentials which at best entitle me to give talks in a silly hat

folklore is fine to tell, and you're pretty good at it. you manage to cram a lot of detail in without the prose disintegrating to default. maybe because you've told this story before.

tef
May 30, 2004

-> some l-system crap ->
i will be happier if i was referred to as a "youtube expert"[1].

as that is the only medium in which i have garnered any attention, outside of writing hn bait on tumblr

[1] http://i.imgur.com/rhtx8kr.png

tef fucked around with this message at 17:58 on Oct 31, 2014

Adbot
ADBOT LOVES YOU

kitten emergency
Jan 13, 2008

get meow this wack-ass crystal prison

tef posted:

i will be happier if i was referred to as a "youtube expert"[1].

as that is the only medium in which i have garnered any attention, outside of writing hn bait on tumblr

[1] http://i.imgur.com/rhtx8kr.png

pretty sure you're a twitter thought leader

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