In-Process Servers
As mentioned previously, in-process servers are a major enhancement in serverSK. Program 12-3 shows how to write a DLL to provide these services. Two familiar functions are shown, a word counting function and a toupper function.By convention, the first parameter is the command line, while the second is the name of the output file. Beyond that, always remember that the function will execute in the same thread as the server thread, so there are strict requirements for thread safety, including but not limited to the following.
- The functions should not change the process environment in any way. For example, if one of the functions changes the working directory, that change will affect the entire process.
- Similarly, the functions should not redirect standard input or output.
- Programming errors, such as allowing a subscript or pointer to go out of bounds or the stack to overflow, could corrupt another thread or the server process itself.
- Resource leaks, such as failing to deallocate memory or to close handles, will ultimately affect the server system.
Processes do not have such stringent requirements because a process cannot normally corrupt other processes, and resources are freed when the process terminates. A typical development methodology, then, is to develop and debug a service as a process, and when it is judged to be reliable, it can be converted to a DLL.Program 12-3 shows a small DLL library with two functions.
Program 12-3. command: Sample In-Process Servers
/* Chapter 12. commands.c. */
/* In-process server commands to use with serverSK, etc. */
/* There are several commands implemented as DLLs. */
/* Each command function must be a thread-safe function */
/* and take two parameters. The first is a string: */
/* command arg1 arg2 ... argn (i.e., a normal command line) */
/* and the second is the file name for the output.
... */
static void extract_token (int, char *, char *);
_declspec (dllexport)
int wcip (char * command, char * output_file)
/* Word count; in process. */
/* NOTE: Simple version; results may differ from wc utility. */
{
. . .
extract_token (1, command, input_file);
fin = fopen (input_file, "r");
/* ... */
ch = nw = nc = nl = 0;
while ((c = fgetc (fin)) != EOF) {
/* ... Standard code -- not important for example ... */
}
fclose (fin);
/* Write the results. */
fout = fopen (output_file, "w");
if (fout == NULL) return 2;
fprintf (fout, " %9d %9d %9d %s\n", nl, nw, nc, input_file);
fclose (fout);
return 0;
}
_declspec (dllexport)
int toupperip (char * command, char * output_file)
/* Convert input to uppercase; in process. */
/* Input file is the second token ("toupperip" is the first). */
{
/* ... */
extract_token (1, command, input_file);
fin = fopen (input_file, "r");
if (fin == NULL) return 1;
fout = fopen (output_file, "w");
if (fout == NULL) return 2;
while ((c = fgetc (fin)) != EOF) {
if (c == '\0') break;
if (isalpha(c)) c = toupper(c);
fputc (c, fout);
}
fclose (fin); fclose (fout);
return 0;
}
static void extract_token (int it, char * command, char * token)
{
/* Extract token number "it" (first token is number 0) */
/* from "command." Result goes in "token." */
/* Tokens are white space delimited.
... */
return;
}
