ref: 59e2dec77517ce76c245405c1b740e33c32a0598
parent: 485b939b9b01e00ab47cd34a9de4a4e901d96a33
parent: 398275d2b5b8a97e3630c7d11340a163871d31d1
author: Simon Howard <fraggle@soulsphere.org>
date: Sat Aug 3 21:05:23 EDT 2019
Merge pull request #1186 from chocolate-doom/writefilerace2 Clean up of midiproc interface to prevent race conditions.
--- a/midiproc/main.c
+++ b/midiproc/main.c
@@ -119,7 +119,6 @@
static boolean RegisterSong(const char *filename)
{
- UnregisterSong();
music = Mix_LoadMUS(filename);
// Remove the temporary MIDI file
@@ -165,9 +164,6 @@
static boolean MidiPipe_RegisterSong(buffer_reader_t *reader)
{
- CHAR buffer[2];
- DWORD bytes_written;
-
char *filename = Reader_ReadString(reader);
if (filename == NULL)
{
@@ -174,20 +170,12 @@
return false;
}
- if (!RegisterSong(filename))
- {
- return false;
- }
+ return RegisterSong(filename);
+}
- if (!WriteInt16(buffer, sizeof(buffer),
- MIDIPIPE_PACKET_TYPE_REGISTER_SONG_ACK))
- {
- return false;
- }
-
- WriteFile(midi_process_out, buffer, sizeof(buffer),
- &bytes_written, NULL);
-
+static boolean MidiPipe_UnregisterSong(buffer_reader_t *reader)
+{
+ UnregisterSong();
return true;
}
@@ -222,7 +210,6 @@
boolean MidiPipe_StopSong()
{
StopSong();
- UnregisterSong();
return true;
}
@@ -246,6 +233,8 @@
{
case MIDIPIPE_PACKET_TYPE_REGISTER_SONG:
return MidiPipe_RegisterSong(reader);
+ case MIDIPIPE_PACKET_TYPE_UNREGISTER_SONG:
+ return MidiPipe_UnregisterSong(reader);
case MIDIPIPE_PACKET_TYPE_SET_VOLUME:
return MidiPipe_SetVolume(reader);
case MIDIPIPE_PACKET_TYPE_PLAY_SONG:
@@ -264,6 +253,8 @@
//
boolean ParseMessage(buffer_t *buf)
{
+ CHAR buffer[2];
+ DWORD bytes_written;
int bytes_read;
uint16_t command;
buffer_reader_t *reader = NewReader(buf);
@@ -285,6 +276,15 @@
bytes_read = Reader_BytesRead(reader);
DeleteReader(reader);
Buffer_Shift(buf, bytes_read);
+
+ // Send acknowledgement back that the command has completed.
+ if (!WriteInt16(buffer, sizeof(buffer), MIDIPIPE_PACKET_TYPE_ACK))
+ {
+ goto fail;
+ }
+
+ WriteFile(midi_process_out, buffer, sizeof(buffer),
+ &bytes_written, NULL);
return true;
--- a/midiproc/proto.h
+++ b/midiproc/proto.h
@@ -20,11 +20,13 @@
typedef enum {
MIDIPIPE_PACKET_TYPE_REGISTER_SONG,
- MIDIPIPE_PACKET_TYPE_REGISTER_SONG_ACK,
+ MIDIPIPE_PACKET_TYPE__DEPRECATED_1,
MIDIPIPE_PACKET_TYPE_SET_VOLUME,
MIDIPIPE_PACKET_TYPE_PLAY_SONG,
MIDIPIPE_PACKET_TYPE_STOP_SONG,
- MIDIPIPE_PACKET_TYPE_SHUTDOWN
+ MIDIPIPE_PACKET_TYPE_SHUTDOWN,
+ MIDIPIPE_PACKET_TYPE_UNREGISTER_SONG,
+ MIDIPIPE_PACKET_TYPE_ACK,
} net_midipipe_packet_type_t;
#endif
--- a/src/i_midipipe.c
+++ b/src/i_midipipe.c
@@ -215,6 +215,19 @@
*(fp + 1) = '\0';
}
+static boolean BlockForAck(void)
+{
+ boolean ok;
+ net_packet_t *packet;
+
+ packet = NET_NewPacket(2);
+ NET_WriteInt16(packet, MIDIPIPE_PACKET_TYPE_ACK);
+ ok = ExpectPipe(packet);
+ NET_FreePacket(packet);
+
+ return ok;
+}
+
//=============================================================================
//
// Protocol Commands
@@ -239,6 +252,7 @@
midi_server_registered = false;
+ ok = ok && BlockForAck();
if (!ok)
{
DEBUGOUT("I_MidiPipe_RegisterSong failed");
@@ -245,21 +259,37 @@
return false;
}
- packet = NET_NewPacket(2);
- NET_WriteInt16(packet, MIDIPIPE_PACKET_TYPE_REGISTER_SONG_ACK);
- ok = ExpectPipe(packet);
+ midi_server_registered = true;
+
+ DEBUGOUT("I_MidiPipe_RegisterSong succeeded");
+ return true;
+}
+
+//
+// I_MidiPipe_UnregisterSong
+//
+// Tells the MIDI subprocess to unload the current song.
+//
+void I_MidiPipe_UnregisterSong(void)
+{
+ boolean ok;
+ net_packet_t *packet;
+
+ packet = NET_NewPacket(64);
+ NET_WriteInt16(packet, MIDIPIPE_PACKET_TYPE_UNREGISTER_SONG);
+ ok = WritePipe(packet);
NET_FreePacket(packet);
+ ok = ok && BlockForAck();
if (!ok)
{
- DEBUGOUT("I_MidiPipe_RegisterSong ack failed");
- return false;
+ DEBUGOUT("I_MidiPipe_UnregisterSong failed");
+ return;
}
- midi_server_registered = true;
+ midi_server_registered = false;
- DEBUGOUT("I_MidiPipe_RegisterSong succeeded");
- return true;
+ DEBUGOUT("I_MidiPipe_UnregisterSong succeeded");
}
//
@@ -278,6 +308,7 @@
ok = WritePipe(packet);
NET_FreePacket(packet);
+ ok = ok && BlockForAck();
if (!ok)
{
DEBUGOUT("I_MidiPipe_SetVolume failed");
@@ -303,6 +334,7 @@
ok = WritePipe(packet);
NET_FreePacket(packet);
+ ok = ok && BlockForAck();
if (!ok)
{
DEBUGOUT("I_MidiPipe_PlaySong failed");
@@ -329,6 +361,7 @@
midi_server_registered = false;
+ ok = ok && BlockForAck();
if (!ok)
{
DEBUGOUT("I_MidiPipe_StopSong failed");
@@ -353,6 +386,7 @@
ok = WritePipe(packet);
NET_FreePacket(packet);
+ ok = ok && BlockForAck();
FreePipes();
midi_server_initialized = false;
--- a/src/i_midipipe.h
+++ b/src/i_midipipe.h
@@ -29,6 +29,7 @@
extern boolean midi_server_registered;
boolean I_MidiPipe_RegisterSong(char *filename);
+void I_MidiPipe_UnregisterSong(void);
void I_MidiPipe_SetVolume(int vol);
void I_MidiPipe_PlaySong(int loops);
void I_MidiPipe_StopSong();
--- a/src/i_sdlmusic.c
+++ b/src/i_sdlmusic.c
@@ -345,12 +345,19 @@
return;
}
- if (handle == NULL)
+#if defined(_WIN32)
+ if (midi_server_registered)
{
- return;
+ I_MidiPipe_StopSong();
}
-
- Mix_FreeMusic(music);
+ else
+#endif
+ {
+ if (handle != NULL)
+ {
+ Mix_FreeMusic(music);
+ }
+ }
}
// Determine whether memory block is a .mid file