From 9565edee8e5eb14aa79f87d669f1b83170f77878 Mon Sep 17 00:00:00 2001 From: Karl Heyes Date: Tue, 28 Jul 2009 14:44:15 +0000 Subject: [PATCH] kh12. A couple of leaks plugged on relay restarting, a possible crash on xml reload or server exit. small changes for win32, the icecast service should be working better and I've updated the libogg to 1.1.4 for the build. svn path=/icecast/branches/kh/icecast/; revision=16352 --- NEWS | 8 ++ config.h.vc6 | 2 +- configure.in | 2 +- src/client.c | 52 ++++++++----- src/main.c | 23 ++++-- src/slave.c | 25 ++++-- src/source.c | 37 +++++---- src/source.h | 1 + src/util.c | 8 +- win32/Icecast2win.clw | 83 +++++++++++++++++++- win32/Icecast2win.dsp | 4 +- win32/Icecast2winDlg.cpp | 7 +- win32/Icecast2winDlg.h | 1 + win32/icecast2.iss | 28 ++++--- win32/icecast2_console.dsp | 4 +- win32/icecastService.cpp | 156 ++++++++++++------------------------- win32/icecastService.dsp | 6 +- 17 files changed, 261 insertions(+), 186 deletions(-) diff --git a/NEWS b/NEWS index 8c2b3a26..160cd05d 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,14 @@ Feature differences from SVN trunk any extra tags are show in the conf/icecast.xml.dist file +2.3.2-kh12 +. xml based relays could cause a crash on server exit or xml reload +. avoid memory/fd leak on active relay restart. +. cleaner worker thread shutdown. +. win32 update. Prevent Esc closing the GUI. Make the service work better and + is now able to take an alternative xml as parameter. Update libogg in the + build to 1.1.4 and refer to the current directory for dependent DLLs. + 2.3.2-kh11 . busy looping caused by truncation on 32bit setups . avoid possible deadlock between file release and open diff --git a/config.h.vc6 b/config.h.vc6 index 021dfbb8..e1491c60 100644 --- a/config.h.vc6 +++ b/config.h.vc6 @@ -95,7 +95,7 @@ #define PACKAGE_NAME "Icecast" /* Version number of package */ -#define VERSION "2.3.2-kh11" +#define VERSION "2.3.2-kh12" /* Define to the version of this package. */ #define PACKAGE_VERSION VERSION diff --git a/configure.in b/configure.in index 9e7725d0..97022641 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -AC_INIT([Icecast], [2.3.2-kh11], [karl@xiph.org]) +AC_INIT([Icecast], [2.3.2-kh12], [karl@xiph.org]) AC_PREREQ(2.59) AC_CONFIG_SRCDIR(src/main.c) diff --git a/src/client.c b/src/client.c index 0d64c0cc..d32296c4 100644 --- a/src/client.c +++ b/src/client.c @@ -372,8 +372,10 @@ void *worker (void *arg) wakeup_time = handler->current_time; prevp = &handler->clients; - while (handler->running) + while (1) { + if (handler->running == 0 && handler->count == 0) + break; if (prev_count != handler->count) { DEBUG2 ("%p now has %d clients", handler, handler->count); @@ -425,8 +427,9 @@ void *worker (void *arg) client = *prevp; } handler->wakeup_ms += 10; /* allow a small sleep */ - wakeup_time.tv_sec = handler->wakeup_ms/1000; - wakeup_time.tv_nsec = (handler->wakeup_ms%1000) *1000000; + + wakeup_time.tv_sec = (long)(handler->wakeup_ms/1000); + wakeup_time.tv_nsec = (long)((handler->wakeup_ms - (wakeup_time.tv_sec*1000))*1000000); } thread_mutex_unlock (&handler->lock); INFO0 ("shutting down"); @@ -459,34 +462,41 @@ static void worker_stop (void) workers = handler->next; worker_count--; thread_rwlock_unlock (&workers_lock); - handler->running = 0; + thread_mutex_lock (&handler->lock); + handler->running = 0; + thread_cond_signal (&handler->cond); + thread_mutex_unlock (&handler->lock); + + thread_sleep (10000); thread_mutex_lock (&handler->lock); clients = handler->clients; handler->clients = NULL; handler->count = 0; thread_cond_signal (&handler->cond); thread_mutex_unlock (&handler->lock); - // move clients to another handler - if (worker_count > 1 && clients) + if (clients) { - client_t *endp = clients; - int count = 0; - - thread_mutex_lock (&workers->lock); - while (endp->next_on_worker) + if (worker_count == 0) + WARN0 ("clients left unprocessed"); + else { - endp = endp->next_on_worker; - count++; - } - endp->next_on_worker = workers->clients; - workers->clients = clients; - workers->count += count; - thread_mutex_unlock (&workers->lock); - } - if (handler->count) - WARN1 ("%d clients left", handler->count); + // move clients to another worker + client_t *endp = clients; + int count = 0; + thread_mutex_lock (&workers->lock); + while (endp->next_on_worker) + { + endp = endp->next_on_worker; + count++; + } + endp->next_on_worker = workers->clients; + workers->clients = clients; + workers->count += count; + thread_mutex_unlock (&workers->lock); + } + } thread_join (handler->thread); thread_mutex_destroy (&handler->lock); thread_cond_destroy (&handler->cond); diff --git a/src/main.c b/src/main.c index 75fb1d97..09953256 100644 --- a/src/main.c +++ b/src/main.c @@ -14,9 +14,15 @@ #ifdef HAVE_CONFIG_H #include #endif + +#ifdef WIN32_SERVICE +#define _WIN32_WINNT 0x0400 +#include +#endif #include #include +#include #ifdef HAVE_UNISTD_H # include @@ -35,7 +41,6 @@ #include #include #include -#include #endif #include "cfgfile.h" @@ -69,7 +74,9 @@ static char *pidfile = NULL; static void _fatal_error(char *perr) { -#ifdef WIN32 +#ifdef WIN32_SERVICE + MessageBox(NULL, perr, "Error", MB_SERVICE_NOTIFICATION); +#elif defined(WIN32) MessageBox(NULL, perr, "Error", MB_OK); #else fprintf(stdout, "%s\n", perr); @@ -115,13 +122,13 @@ void _initialize_subsystems(void) void _shutdown_subsystems(void) { - fserve_shutdown(); refbuf_shutdown(); slave_shutdown(); auth_shutdown(); yp_shutdown(); stats_shutdown(); + fserve_shutdown(); connection_shutdown(); config_shutdown(); resolver_shutdown(); @@ -431,12 +438,14 @@ int main(int argc, char **argv) _fatal_error("XML config parsing error"); break; } +#if !defined(_WIN32) || defined(_CONSOLE) _shutdown_subsystems(); - return 1; +#endif + return -1; } } else if (res == -1) { _print_usage(); - return 1; + return -1; } /* override config file options with commandline options */ @@ -446,7 +455,7 @@ int main(int argc, char **argv) if(!_server_proc_init()) { _fatal_error("Server startup failed. Exiting"); _shutdown_subsystems(); - return 1; + return -1; } _ch_root_uid_setup(); /* Change user id and root if requested/possible */ @@ -469,7 +478,7 @@ int main(int argc, char **argv) if (!_start_logging()) { _fatal_error("FATAL: Could not start logging"); _shutdown_subsystems(); - return 1; + return -1; } INFO1 ("%s server started", ICECAST_VERSION_STRING); diff --git a/src/slave.c b/src/slave.c index 43866ad2..59f517b9 100644 --- a/src/slave.c +++ b/src/slave.c @@ -228,7 +228,6 @@ void slave_shutdown(void) thread_rwlock_destroy (&slaves_lock); thread_rwlock_destroy (&workers_lock); thread_spin_destroy (&relay_start_lock); - slave_running = 0; } @@ -550,6 +549,7 @@ static void *start_relay_stream (void *arg) config_release_config(); INFO2 ("listener count still on %s is %d", src->mount, src->listeners); + source_clear_listeners (src); source_clear_source (src); relay->start = client->worker->current_time.tv_sec + relay->interval; client->schedule_ms = timing_get_time() + 1000; @@ -725,6 +725,7 @@ static void relay_check_streams (relay_server *to_start, { release->cleanup = 1; release->start = 0; + release->source->client->schedule_ms = 0; if (release->running) { /* relay has been removed from xml/streamlist, shut down active relay */ @@ -1253,8 +1254,15 @@ static int relay_read (client_t *client) client->ops = &relay_startup_ops; relay->running = 0; global_reduce_bitrate_sampling (global.out_bitrate); - thread_mutex_unlock (&source->lock); + if (client->con) + connection_close (client->con); + client->con = NULL; + if (client->parser) + httpp_destroy (client->parser); + client->parser = NULL; + source_clear_source (source); thread_rwlock_unlock (&global.shutdown_lock); + slave_update_all_mounts(); return 0; } if ((source->flags & SOURCE_TERMINATING) == 0) @@ -1272,6 +1280,7 @@ static int relay_read (client_t *client) stats_event (relay->localmount, NULL, NULL); global_reduce_bitrate_sampling (global.out_bitrate); thread_rwlock_unlock (&global.shutdown_lock); + slave_update_all_mounts(); return -1; } @@ -1288,7 +1297,7 @@ static int relay_startup (client_t *client) { relay_server *relay = client->shared_data; - if (global.running != ICE_RUNNING || relay->cleanup) + if (relay->cleanup) return -1; if (relay->enable == 0 || relay->start > client->worker->current_time.tv_sec) { @@ -1300,11 +1309,6 @@ static int relay_startup (client_t *client) { source_t *src = relay->source; src->flags |= SOURCE_ON_DEMAND; - if (src->listeners == 0) - { - client->schedule_ms = client->worker->time_ms + 1000; - return 0; - } if (client->worker->current_time.tv_sec % 10 == 0) { mount_proxy * mountinfo = config_find_mount (config_get_config(), src->mount); @@ -1312,6 +1316,11 @@ static int relay_startup (client_t *client) source_set_override (mountinfo->fallback_mount, src->mount); config_release_config(); } + if (src->listeners == 0) + { + client->schedule_ms = client->worker->time_ms + 1000; + return 0; + } DEBUG1 ("Detected listeners on relay %s", relay->localmount); } diff --git a/src/source.c b/src/source.c index a0389db8..64c2e426 100644 --- a/src/source.c +++ b/src/source.c @@ -229,21 +229,11 @@ int source_compare_sources(void *arg, void *a, void *b) } -void source_clear_source (source_t *source) +void source_clear_listeners (source_t *source) { - int i, do_twice = 0; + int i; ice_config_t *config; mount_proxy *mountinfo; - refbuf_t *p; - - DEBUG1 ("clearing source \"%s\"", source->mount); - - if (source->dumpfile) - { - INFO1 ("Closing dumpfile for %s", source->mount); - fclose (source->dumpfile); - source->dumpfile = NULL; - } /* lets drop any listeners still connected */ DEBUG2 ("source %s has %d clients to release", source->mount, source->listeners); @@ -268,6 +258,24 @@ void source_clear_source (source_t *source) stats_event_sub (NULL, "listeners", i); stats_event_sub (source->mount, "listeners", i); } + source->listeners = 0; + source->prev_listeners = 0; +} + + +void source_clear_source (source_t *source) +{ + int do_twice = 0; + refbuf_t *p; + + DEBUG1 ("clearing source \"%s\"", source->mount); + + if (source->dumpfile) + { + INFO1 ("Closing dumpfile for %s", source->mount); + fclose (source->dumpfile); + source->dumpfile = NULL; + } format_free_plugin (source->format); source->format = NULL; @@ -301,8 +309,6 @@ void source_clear_source (source_t *source) source->burst_offset = 0; source->queue_size = 0; source->queue_size_limit = 0; - source->listeners = 0; - source->prev_listeners = 0; source->client_stats_update = 0; util_dict_free (source->audio_info); source->audio_info = NULL; @@ -326,6 +332,7 @@ void source_clear_source (source_t *source) static int _free_source (void *p) { source_t *source = p; + source_clear_listeners (source); source_clear_source (source); /* make sure all YP entries have gone */ @@ -598,7 +605,6 @@ static int source_client_read (client_t *client) client->ops = &source_client_halt_ops; free (source->fallback.mount); source->fallback.mount = NULL; - stats_event (source->mount, NULL, NULL); } thread_mutex_unlock (&source->lock); } @@ -992,6 +998,7 @@ void source_shutdown (source_t *source, int with_fallback) global.sources--; stats_event_args (NULL, "sources", "%d", global.sources); global_unlock(); + stats_event (source->mount, NULL, NULL); } diff --git a/src/source.h b/src/source.h index be27bca3..b8370669 100644 --- a/src/source.h +++ b/src/source.h @@ -94,6 +94,7 @@ void *source_client_thread (void *arg); int source_startup (client_t *client, const char *uri); int source_client_callback (client_t *client, void *source); void source_update_settings (ice_config_t *config, source_t *source, mount_proxy *mountinfo); +void source_clear_listeners (source_t *source); void source_clear_source (source_t *source); source_t *source_find_mount(const char *mount); source_t *source_find_mount_raw(const char *mount); diff --git a/src/util.c b/src/util.c index 01b18e7e..7a54103c 100644 --- a/src/util.c +++ b/src/util.c @@ -47,14 +47,14 @@ struct rate_calc_node { - uint64_t index; - long value; + int64_t index; + uint64_t value; struct rate_calc_node *next; }; struct rate_calc { - uint64_t total; + int64_t total; struct rate_calc_node *current; unsigned int samples; unsigned int ssec; @@ -755,7 +755,7 @@ void rate_add (struct rate_calc *calc, long value, uint64_t sid) */ long rate_avg (struct rate_calc *calc) { - uint64_t range; + float range; if (calc == NULL || calc->blocks < 2) return 0; diff --git a/win32/Icecast2win.clw b/win32/Icecast2win.clw index 343c35fd..d1e328a5 100644 --- a/win32/Icecast2win.clw +++ b/win32/Icecast2win.clw @@ -12,7 +12,7 @@ Class1=CIcecast2winApp Class2=CIcecast2winDlg Class3=CAboutDlg -ResourceCount=10 +ResourceCount=19 Resource1=IDR_MENU2 Resource2=IDR_MAINFRAME Resource3=IDR_TRAY @@ -26,6 +26,15 @@ Resource7=IDD_STATSDIALOG Resource8=IDR_MENU3 Resource9=IDD_ABOUTBOX Resource10=IDR_MENU4 +Resource11=IDD_SSTATUS (English (U.S.)) +Resource12=IDD_CONFIGDIALOG (English (U.S.)) +Resource13=IDD_STATSDIALOG (English (U.S.)) +Resource14=IDR_MENU2 (English (U.S.)) +Resource15=IDR_MENU3 (English (U.S.)) +Resource16=IDR_TRAY (English (U.S.)) +Resource17=IDD_ABOUTBOX (English (U.S.)) +Resource18=IDD_ICECAST2WIN_DIALOG (English (U.S.)) +Resource19=IDR_MENU4 (English (U.S.)) [CLS:CIcecast2winApp] Type=0 @@ -147,3 +156,75 @@ Command3=ID_ABOUT_HELP Command4=ID_ABOUT_CREDITS CommandCount=4 +[DLG:IDD_ABOUTBOX (English (U.S.))] +Type=1 +Class=? +ControlCount=2 +Control1=IDOK,button,1342373889 +Control2=IDC_STATIC,static,1350572046 + +[DLG:IDD_ICECAST2WIN_DIALOG (English (U.S.))] +Type=1 +Class=? +ControlCount=7 +Control1=IDC_MAINTAB,SysTabControl32,1342177280 +Control2=IDC_START,button,1342242816 +Control3=IDC_AUTOSTART,button,1342251011 +Control4=IDC_STATIC,static,1342177294 +Control5=IDC_SERVERSTATUS,static,1342177294 +Control6=IDC_STATIC_SS,static,1342308865 +Control7=IDC_HIDESYSTRAY,button,1342242816 + +[DLG:IDD_SSTATUS (English (U.S.))] +Type=1 +Class=? +ControlCount=5 +Control1=IDC_FILLER2,static,1342308352 +Control2=IDC_GLOBALSTAT_LIST,SysListView32,1350631425 +Control3=IDC_STATIC_GS,static,1342308352 +Control4=IDC_STATIC_RUN,static,1342308352 +Control5=IDC_RUNNINGFOR,static,1342308352 + +[DLG:IDD_CONFIGDIALOG (English (U.S.))] +Type=1 +Class=? +ControlCount=1 +Control1=IDC_CONFIG,edit,1352732868 + +[DLG:IDD_STATSDIALOG (English (U.S.))] +Type=1 +Class=? +ControlCount=4 +Control1=IDC_STATSLIST,SysListView32,1350631425 +Control2=IDC_SOURCELIST,SysListView32,1350631425 +Control3=IDC_STATIC_SLS,static,1342308352 +Control4=IDC_STATIC,static,1342308352 + +[MNU:IDR_MENU2 (English (U.S.))] +Type=1 +Class=? +Command1=ID_POPUP_ADDTOGLOBALSTATLIST +CommandCount=1 + +[MNU:IDR_MENU3 (English (U.S.))] +Type=1 +Class=? +Command1=ID__DELETEFROMGLOBALSTATS +Command2=ID__MAKETHISSTATTHEWINDOWTITLE +CommandCount=2 + +[MNU:IDR_TRAY (English (U.S.))] +Type=1 +Class=? +Command1=ID_BLANK_RESTORE +CommandCount=1 + +[MNU:IDR_MENU4 (English (U.S.))] +Type=1 +Class=? +Command1=ID_FILE_EXIT +Command2=ID_FILE_EDITCONFIGURATION +Command3=ID_ABOUT_HELP +Command4=ID_ABOUT_CREDITS +CommandCount=4 + diff --git a/win32/Icecast2win.dsp b/win32/Icecast2win.dsp index d8c0fb5a..c1c4789e 100644 --- a/win32/Icecast2win.dsp +++ b/win32/Icecast2win.dsp @@ -53,7 +53,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 /nologo /subsystem:windows /machine:I386 -# ADD LINK32 libspeex.lib theora_static_d.lib ogg_static.lib vorbis_static.lib pthreadVSE.lib ssleay32MT.lib libcurl.lib libxml2.lib libxslt.lib iconv.lib ws2_32.lib winmm.lib /nologo /version:2.3 /subsystem:windows /pdb:none /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmtd.lib" +# ADD LINK32 libspeex.lib theora_static_d.lib ogg.lib vorbis_static.lib pthreadVSE.lib ssleay32MT.lib libcurl.lib libxml2.lib libxslt.lib iconv.lib ws2_32.lib winmm.lib /nologo /version:2.3 /subsystem:windows /pdb:none /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmtd.lib" !ELSEIF "$(CFG)" == "Icecast2win - Win32 Debug" @@ -79,7 +79,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept -# ADD LINK32 libspeex.lib theora_static_d.lib ogg_static.lib vorbis_static.lib pthreadVSE.lib ssleay32MT.lib libcurl.lib libxml2.lib libxslt.lib iconv.lib ws2_32.lib winmm.lib /nologo /version:2.3 /subsystem:windows /incremental:no /debug /machine:I386 /nodefaultlib:"libcd.lib libcmt.lib" /pdbtype:sept +# ADD LINK32 libspeex.lib theora_static_d.lib ogg.lib vorbis_static.lib pthreadVSE.lib ssleay32MT.lib libcurl.lib libxml2.lib libxslt.lib iconv.lib ws2_32.lib winmm.lib /nologo /version:2.3 /subsystem:windows /incremental:no /debug /machine:I386 /nodefaultlib:"libcd.lib libcmt.lib" /pdbtype:sept # SUBTRACT LINK32 /verbose !ENDIF diff --git a/win32/Icecast2winDlg.cpp b/win32/Icecast2winDlg.cpp index 736aee8b..91022911 100644 --- a/win32/Icecast2winDlg.cpp +++ b/win32/Icecast2winDlg.cpp @@ -549,7 +549,7 @@ void StartStats(void *dummy) if (cur == NULL) { MessageBox(NULL, "empty XML document", "Error", MB_OK); xmlFreeDoc(doc); - return; + break; } cur = cur->xmlChildrenNode; @@ -1202,3 +1202,8 @@ void CIcecast2winDlg::OnAboutCredits() CAboutDlg about; about.DoModal(); } + +void CIcecast2winDlg::OnCancel() +{ +} + diff --git a/win32/Icecast2winDlg.h b/win32/Icecast2winDlg.h index c79a5c0a..b83957b7 100644 --- a/win32/Icecast2winDlg.h +++ b/win32/Icecast2winDlg.h @@ -95,6 +95,7 @@ protected: // Generated message map functions //{{AFX_MSG(CIcecast2winDlg) virtual BOOL OnInitDialog(); + virtual void OnCancel(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); diff --git a/win32/icecast2.iss b/win32/icecast2.iss index ff085223..c9dd1d55 100644 --- a/win32/icecast2.iss +++ b/win32/icecast2.iss @@ -3,7 +3,7 @@ [Setup] AppName=Icecast2-KH -AppVerName=Icecast v2.3.2-kh11 +AppVerName=Icecast v2.3.2-kh12 AppPublisherURL=http://www.icecast.org AppSupportURL=http://www.icecast.org AppUpdatesURL=http://www.icecast.org @@ -13,9 +13,11 @@ AllowNoIcons=yes LicenseFile=..\COPYING InfoAfterFile=..\README OutputDir=. -OutputBaseFilename=icecast2_win32_v2.3.2-kh11_setup +OutputBaseFilename=icecast2_win32_v2.3.2-kh12_setup WizardImageFile=icecast2logo2.bmp WizardImageStretch=no +VersionInfoProductVersion=kh12 +VersionInfoVersion=2.3.2 ; uncomment the following line if you want your installation to run on NT 3.51 too. ; MinVersion=4,3.51 @@ -34,8 +36,8 @@ Name: "{app}\examples" Source: "win_release\icecast2win.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "console_release\icecast2_console.exe"; DestDir: "{app}"; DestName: "icecast2console.exe"; Flags: ignoreversion Source: "service_Release\icecastService.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\examples\*"; DestDir: "{app}\examples"; Flags: ignoreversion -Source: "..\doc\*"; DestDir: "{app}\doc"; Flags: ignoreversion +Source: "..\examples\*"; DestDir: "{app}\examples"; Excludes: "*~"; Flags: ignoreversion +Source: "..\doc\*"; DestDir: "{app}\doc"; Excludes: "*Makefile*"; Flags: ignoreversion Source: "..\web\*.xsl"; DestDir: "{app}\web"; Flags: ignoreversion Source: "..\web\*.html"; DestDir: "{app}\web"; Flags: ignoreversion Source: "..\web\images\*.png"; DestDir: "{app}\web\images"; Flags: ignoreversion @@ -43,16 +45,18 @@ Source: "..\web\images\*.jpg"; DestDir: "{app}\web\images"; Flags: ignoreversion Source: "..\web\*.css"; DestDir: "{app}\web"; Flags: ignoreversion Source: "..\admin\*.xsl"; DestDir: "{app}\admin"; Flags: ignoreversion Source: "..\admin\flashpolicy"; DestDir: "{app}\admin"; Flags: ignoreversion -Source: "c:\xiph\lib\pthreadVSE.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "..\conf\*.dist"; DestDir: "{app}"; Flags: ignoreversion Source: "..\examples\icecast_shoutcast_compat.xml"; DestDir: "{app}"; DestName: "icecast.xml"; Flags: ignoreversion confirmoverwrite -Source: "c:\xiph\lib\iconv.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "c:\xiph\lib\libxslt.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "c:\xiph\lib\libxml2.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "c:\xiph\lib\libcurl.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "c:\xiph\lib\libeay32.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "c:\xiph\lib\ssleay32.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "c:\xiph\lib\zlib1.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: ".\pthreadVSE.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: ".\iconv.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: ".\ogg.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: ".\libspeex.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: ".\libxslt.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: ".\libxml2.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: ".\libcurl.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: ".\libeay32.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: ".\ssleay32.dll"; DestDir: "{app}"; Flags: ignoreversion +Source: ".\zlib1.dll"; DestDir: "{app}"; Flags: ignoreversion [Icons] diff --git a/win32/icecast2_console.dsp b/win32/icecast2_console.dsp index c79da3a6..96519b38 100644 --- a/win32/icecast2_console.dsp +++ b/win32/icecast2_console.dsp @@ -50,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 theora_static_d.lib libspeex.lib ogg_static.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libcurl.lib vorbis_static.lib libxml2.lib libxslt.lib iconv.lib pthreadVSE.lib ws2_32.lib winmm.lib ssleay32MT.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmt.lib" +# ADD LINK32 theora_static_d.lib libspeex.lib ogg.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libcurl.lib vorbis_static.lib libxml2.lib libxslt.lib iconv.lib pthreadVSE.lib ws2_32.lib winmm.lib ssleay32MT.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libc.lib" /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmt.lib" # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "icecast2 console - Win32 Debug" @@ -75,7 +75,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 theora_static_d.lib libspeex.lib ogg_static.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libcurl.lib vorbis_static.lib libxml2.lib libxslt.lib iconv.lib pthreadVSE.lib ws2_32.lib winmm.lib ssleay32MT.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /nodefaultlib:"libcmt.lib" /nodefaultlib:"libcmtd.lib" /pdbtype:sept +# ADD LINK32 theora_static_d.lib libspeex.lib ogg.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libcurl.lib vorbis_static.lib libxml2.lib libxslt.lib iconv.lib pthreadVSE.lib ws2_32.lib winmm.lib ssleay32MT.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /nodefaultlib:"libcmt.lib" /nodefaultlib:"libcmtd.lib" /pdbtype:sept # SUBTRACT LINK32 /pdb:none !ENDIF diff --git a/win32/icecastService.cpp b/win32/icecastService.cpp index ade738ec..3086edab 100644 --- a/win32/icecastService.cpp +++ b/win32/icecastService.cpp @@ -1,6 +1,9 @@ #include +#define _WIN32_WINNT 0x0400 +#include #include #include + extern "C" { #include "thread/thread.h" #include "avl/avl.h" @@ -24,19 +27,13 @@ SERVICE_STATUS_HANDLE hStatus; void ServiceMain(int argc, char** argv); void ControlHandler(DWORD request); -int InitService(); extern "C" int mainService(int argc, char **argv); -int InitService() -{ - int result = 0; - return(result); -} void installService (const char *path) { if (path) { - char buffer[8096*2] = "\""; + TCHAR buffer [MAX_PATH] = "\""; int len = GetModuleFileName (NULL, buffer+1, sizeof (buffer)-1); _snprintf (buffer+len+1, sizeof (buffer)-len, "\" \"%s\"", path); @@ -44,21 +41,7 @@ void installService (const char *path) SC_HANDLE manager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if (manager == NULL) { - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - - printf ("OpenSCManager: %s\n", (LPCTSTR)lpMsgBuf); - LocalFree( lpMsgBuf ); + MessageBox (NULL, "OpenSCManager failed", NULL, MB_SERVICE_NOTIFICATION); return; } @@ -79,21 +62,7 @@ void installService (const char *path) ); if (service == NULL) { - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - - printf ("CreateService: %s\n", (LPCTSTR)lpMsgBuf); - LocalFree( lpMsgBuf ); + MessageBox (NULL, "CreateService failed", NULL, MB_SERVICE_NOTIFICATION); CloseServiceHandle (manager); return; } @@ -108,94 +77,67 @@ void removeService() SC_HANDLE manager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if (manager == NULL) { - LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - - printf ("OpenSCManager: %s\n", (LPCTSTR)lpMsgBuf); - LocalFree( lpMsgBuf ); + MessageBox (NULL, "OpenSCManager failed", NULL, MB_SERVICE_NOTIFICATION); return; } SC_HANDLE service = OpenService (manager, PACKAGE_STRING, DELETE); if (service) { DeleteService(service); - printf ("Service Removed\n"); CloseServiceHandle (service); + printf ("Service deleted, may require reboot to complete removal\n"); } - else + else printf ("Service not found\n"); CloseServiceHandle (manager); + Sleep (1500); } void ControlHandler(DWORD request) { switch(request) { case SERVICE_CONTROL_STOP: - global.running = ICE_HALTING; - ServiceStatus.dwWin32ExitCode = 0; - ServiceStatus.dwCurrentState = SERVICE_STOPPED; - SetServiceStatus (hStatus, &ServiceStatus); - return; + if (ServiceStatus.dwCurrentState != SERVICE_STOP) + { + ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus (hStatus, &ServiceStatus); + global.running = ICE_HALTING; + return; + } - case SERVICE_CONTROL_SHUTDOWN: - global.running = ICE_HALTING; - ServiceStatus.dwWin32ExitCode = 0; - ServiceStatus.dwCurrentState = SERVICE_STOPPED; - SetServiceStatus (hStatus, &ServiceStatus); - return; default: break; } // Report current status SetServiceStatus (hStatus, &ServiceStatus); - - return; } void ServiceMain(int argc, char** argv) { - int error; - - ServiceStatus.dwServiceType = SERVICE_WIN32; - ServiceStatus.dwCurrentState = SERVICE_START_PENDING; - ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; - ServiceStatus.dwWin32ExitCode = 0; - ServiceStatus.dwServiceSpecificExitCode = 0; - ServiceStatus.dwCheckPoint = 0; - ServiceStatus.dwWaitHint = 0; - - hStatus = RegisterServiceCtrlHandler(PACKAGE_STRING, (LPHANDLER_FUNCTION)ControlHandler); - if (hStatus == (SERVICE_STATUS_HANDLE)0) { - // Registering Control Handler failed - return; - } - // Initialize Service - error = InitService(); - if (error) { - // Initialization failed - ServiceStatus.dwCurrentState = SERVICE_STOPPED; - ServiceStatus.dwWin32ExitCode = -1; - SetServiceStatus(hStatus, &ServiceStatus); - return; - } - // We report the running status to SCM. - ServiceStatus.dwCurrentState = SERVICE_RUNNING; - SetServiceStatus (hStatus, &ServiceStatus); - - /* Here we do the work */ + ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ServiceStatus.dwCurrentState = SERVICE_START_PENDING; + ServiceStatus.dwControlsAccepted = 0; + ServiceStatus.dwWin32ExitCode = 0; + ServiceStatus.dwServiceSpecificExitCode = 0; + ServiceStatus.dwCheckPoint = 0; + ServiceStatus.dwWaitHint = 0; - int argc2 = 3; - char* argv2 [3]; + hStatus = RegisterServiceCtrlHandler(PACKAGE_STRING, (LPHANDLER_FUNCTION)ControlHandler); + if (hStatus == (SERVICE_STATUS_HANDLE)0) { + // Registering Control Handler failed + MessageBox (NULL, "RegisterServiceCtrlHandler failed", NULL, MB_SERVICE_NOTIFICATION); + return; + } + + // We report the running status to SCM. + ServiceStatus.dwCurrentState = SERVICE_RUNNING; + ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + SetServiceStatus (hStatus, &ServiceStatus); + + /* Here we do the work */ + + int argc2 = 3; + char* argv2 [3]; argv2 [0] = argv[0]; argv2 [1] = "-c"; @@ -204,12 +146,10 @@ void ServiceMain(int argc, char** argv) else argv2 [2] = argv[1]; - int ret = mainService(argc2, (char **)argv2); + ServiceStatus.dwWin32ExitCode = mainService(argc2, (char **)argv2); - ServiceStatus.dwCurrentState = SERVICE_STOPPED; - ServiceStatus.dwWin32ExitCode = -1; - SetServiceStatus(hStatus, &ServiceStatus); - return; + ServiceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(hStatus, &ServiceStatus); } @@ -232,15 +172,14 @@ void main(int argc, char *argv[]) if (!strcmp(argv[1], "remove") || !strcmp(argv[1], "uninstall")) { removeService(); - printf ("service removed, may require a reboot\n"); - Sleep (1000); return; } if (_chdir(argv[1]) < 0) { - printf ("unable to change to directory %s\n", argv[1]); - Sleep (1000); + char buffer [256]; + _snprintf (buffer, sizeof(buffer), "Unable to change to directory %s", argv[1]); + MessageBox (NULL, buffer, NULL, MB_SERVICE_NOTIFICATION); return; } @@ -251,5 +190,6 @@ void main(int argc, char *argv[]) ServiceTable[1].lpServiceName = NULL; ServiceTable[1].lpServiceProc = NULL; // Start the control dispatcher thread for our service - StartServiceCtrlDispatcher(ServiceTable); + if (StartServiceCtrlDispatcher (ServiceTable) == 0) + MessageBox (NULL, "StartServiceCtrlDispatcher failed", NULL, MB_SERVICE_NOTIFICATION); } diff --git a/win32/icecastService.dsp b/win32/icecastService.dsp index c8b6dfb3..83daef09 100644 --- a/win32/icecastService.dsp +++ b/win32/icecastService.dsp @@ -50,7 +50,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 libspeex.lib theora_static_d.lib ogg_static.lib vorbis_static.lib pthreadVSE.lib ssleay32MT.lib libcurl.lib libxml2.lib libxslt.lib ws2_32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /machine:I386 /nodefaultlib:"libcmt.lib" /nodefaultlib:"libcmtd.lib" /nodefaultlib:"libcd.lib" +# ADD LINK32 libspeex.lib theora_static_d.lib ogg.lib vorbis_static.lib pthreadVSE.lib ssleay32MT.lib libcurl.lib libxml2.lib libxslt.lib ws2_32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /machine:I386 /nodefaultlib:"libcmt.lib" /nodefaultlib:"libcmtd.lib" /nodefaultlib:"libcd.lib" !ELSEIF "$(CFG)" == "icecastService - Win32 Debug" @@ -66,7 +66,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /GX /Zd /Od /I ".." /I "..\src" /D "_DEBUG" /D HAVE_CONFIG_H=1 /D "_CONSOLE" /D "WIN32_SERVICE" /D "WIN32" /D "_MBCS" /FR /YX /FD /GZ /c +# ADD CPP /nologo /W3 /GX /Zd /Od /I ".." /I "..\src" /D "_DEBUG" /D HAVE_CONFIG_H=1 /D "_CONSOLE" /D "WIN32_SERVICE" /D "WIN32" /D "_MBCS" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -74,7 +74,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 vorbis_static.lib iconv.lib libspeex.lib theora_static_d.lib ogg_static_d.lib vorbis_static_d.lib pthreadVSE.lib ssleay32MT.lib libcurl.lib libxml2.lib libxslt.lib ws2_32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /nodefaultlib:"libcd.lib" /nodefaultlib:"libcmt.lib" /out:"service_debug/icecast2service.exe" /pdbtype:sept +# ADD LINK32 vorbis_static.lib iconv.lib libspeex.lib theora_static_d.lib ogg.lib vorbis_static_d.lib pthreadVSE.lib ssleay32MT.lib libcurl.lib libxml2.lib libxslt.lib ws2_32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /nodefaultlib:"libcmtd" /nodefaultlib:"libcmt" /force /out:"service_debug/icecast2service.exe" /pdbtype:sept # SUBTRACT LINK32 /pdb:none !ENDIF